Skip to content

Conversation

@Jeremie-Kiwik
Copy link
Contributor

@Jeremie-Kiwik Jeremie-Kiwik commented Nov 21, 2025

Questions Answers
Description? Add specific price endpoints
Type? improvement
BC breaks? no
Deprecations? no
Fixed ticket?
Sponsor company KIWIK
How to test? See below

Endpoints summary

POST /admin-api/products/specific-prices
PATCH /admin-api/products/specific-prices/{specificPriceId}
DEL /admin-api/products/specific-prices/{specificPriceId}

GET /admin-api/products/{productId}/specific-prices
GET /admin-api/products/specific-prices/{specificPriceId}

PATCH /admin-api/products/{productId}/specific-price-priorities
DEL /admin-api/products/{productId}/specific-price-priorities

EDIT 2025-11-26

I have updated this PR to follow the new conventions, which require endpoint names to be in the plural form.

Discussions

JSON keys standardization: reductionValue vs reductionAmount

PrestaShop core presents an inconsistency in property names:

  • GetSpecificPriceForEditing (used for GET/UPDATE) exposes reductionAmount via getReductionAmount()
  • GetSpecificPriceList (used for LIST) exposes reductionValue via getReductionValue()
  • Commands (AddSpecificPriceCommand, EditSpecificPriceCommand) use reductionValue as parameter in setReduction()

Technical choice: Use reductionValue everywhere in the API (input and output) to:

  • Stay consistent with CQRS commands that use reductionValue
  • Avoid semantic confusion: "amount" suggests a fixed amount, while reduction can be a percentage

Implementation: Mapping [reductionAmount][reductionValue] in QUERY_MAPPING to transform GetSpecificPriceForEditing response to API Resource.

Specific price priority: hard-coding choices

Specific price priorities are declared in PriorityList::AVAILABLE_PRIORITIES.
My implementation limits allowed values via an Assert\Choice constraint with a hard-coded list:

  • id_group
  • id_currency
  • id_country
  • id_shop

That way, the admin API validation provides clear and immediate error feedback. And priorities are stable business constants in PrestaShop.
As this is my own opinion, feel free to discuss this point!

Notice: mapping reductionType / reductionValue for partial updates

The PATCH endpoint uses EditSpecificPriceCommand::setReduction(string $reductionType, string $reductionValue) which expects two distinct parameters.

Technical choice: Transformation via UPDATE_COMMAND_MAPPING:

  • [reductionType][reduction][reductionType]
  • [reductionValue][reduction][reductionValue]

The CQRSApiNormalizer automatically detects methods with multiple parameters and calls setReduction() with values from the reduction array. This approach allows handling partial updates while respecting the CQRS command signature.

How to test

Create an API Client with these scopes : product_read & product_write
Request an access token

Create a specific price

  • Method : POST
  • URI : /admin-api/products/specific-prices
  • Body :
{
  "productId": 5,
  "reductionType": "percentage",
  "reductionValue": "10.5",
  "includeTax": true,
  "fixedPrice": "-1",
  "fromQuantity": 1,
  "dateTimeFrom": "0000-00-00T00:00:00+00:00",
  "dateTimeTo": "0000-00-00T00:00:00+00:00"
}
  • Response :
    HTTP Code : 201
    HTTP Body : the created specific price, with an ID that we will use as {createdID} for other calls

Update a specific price

  • Method : PATCH
  • URI : /admin-api/products/specific-prices/{createdID}
  • Body :
{
  "reductionType": "percentage",
  "reductionValue": "20.0",
  "includesTax": true,
  "fromQuantity": 5,
  "dateTimeFrom": "2025-01-01T00:00:00+00:00",
  "dateTimeTo": "2025-12-31T23:59:59+00:00"
}
  • Response :
    HTTP Code : 200
    HTTP Body : updated specific price, with updated values

Get a specific price

  • Method : GET
  • URI : /admin-api/products/specific-prices/{createdID}
  • Body : none
  • Response :
    HTTP Code : 200
    HTTP Body : the specific price with ID {createdID}

List specific prices for a product

  • Method : GET
  • URI : /admin-api/products/{productId}/specific-prices
  • Body : none
  • Response :
    HTTP Code : 200
    HTTP Body : array of specific prices for the product

Set specific price priority for a product

  • Method : PATCH
  • URI : /admin-api/products/{productId}/specific-price-priorities
  • Body :
{
    "priorities": [
        "id_shop", "id_country", "id_currency", "id_group"
    ]
}
  • Response :
    HTTP Code : 204
    HTTP Body : (no content)

Remove specific price priority (reset to default)

  • Method : DELETE
  • URI : /admin-api/products/{productId}/specific-price-priorities
  • Body : none
  • Response :
    HTTP Code : 204
    Result: specific price priority is reset to default for the product

Delete a specific price

  • Method : DELETE
  • URI : /admin-api/products/specific-prices/{createdID}
  • Body : none
  • Response :
    HTTP Code : 204
    Result: specific price with ID {createdID} is deleted

Copy link
Contributor

@nicosomb nicosomb left a comment

Choose a reason for hiding this comment

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

About src/ApiPlatform/Normalizer/DateTimeImmutableNormalizer.php, we plan to change the fields, to make them as nullable.
So this kind of hack won't be useful anymore.

@boherm @jolelievre @tleon are we ok with that?

@ps-jarvis ps-jarvis moved this from Ready for review to Waiting for author in PR Dashboard Nov 24, 2025
@Jeremie-Kiwik
Copy link
Contributor Author

I’ve updated my code to follow the new conventions that require endpoint names to be plural.
Let me know if I need to do anything regarding the DateTimeImmutableNormalizer

@kpodemski
Copy link
Contributor

Hello @Jeremie-Kiwik

From what I see, most changes are ok, but there is a conflict in services.yml that has to be resolved before continuing, which probably appeared once we merged your other PR.

@Jeremie-Kiwik
Copy link
Contributor Author

@kpodemski I rebased the PR and merged services.yml. It should be OK now!

Copy link
Contributor

@jolelievre jolelievre left a comment

Choose a reason for hiding this comment

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

Sorry many PRs have passed similar to this one but this module is not supposed to contain serialization logic nor providers

The core is meant to include all this generic logic and the module is only there for configuration, very often the core alreay allows handling use cases with the proper configuration and if it can't then the core should evolve not the module

Can you explain the reason why you needed a dedicated normalizer and a specific provider?

@kpodemski
Copy link
Contributor

Hello @Jeremie-Kiwik

Just a quick heads-up: reviews on pending Admin API PRs will start in the coming days.

We first took some time to clarify and unify the Admin API contribution rules and ADR expectations. With that work done, the team will now review existing PRs based on those updates.

Please note that, based on the updated standards described here:
https://devdocs.prestashop-project.org/9/admin-api/contribute-to-core-api/

some aspects of this PR currently do not meet the requirements. For this reason, I've added the Invalid label for now.

I see that @jolelievre asked about some of those aspects already. Could you please take a moment to answer us?

Thanks for your patience.

@kpodemski kpodemski added the Invalid This doesn't seem right label Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Waiting for author

Development

Successfully merging this pull request may close these issues.

5 participants