- Issue created by @morbus iff
If a site has only one order type created, the Promotions UI will not show the "Order type" checkbox. However, order type is still silently required when creating a Promotion programmatically, and set order types will not be shown in the JSON:API. This caused us a day of discovery before we could nail down why our programmatically-created Promotions were not applying.
Our original pseudo-code looked like the following.
$basePromotion = Promotion::create([
'uid' => \Drupal::currentUser()->id(),
'name' => $basePromotionName,
'require_coupon' => TRUE,
'compatibility' => 'any',
'offer' => [
'target_plugin_id' => 'order_item_percentage_off',
'target_plugin_configuration' => [
'percentage' => '1',
'display_inclusive' => FALSE,
'operator' => 'OR',
'conditions' => [
'target_plugin_configuration' => [
'plugin' => 'order_item_purchased_entity:commerce_product_variation',
'configuration' => [
'entities' => [
$productVariation->id() => $productVariation->uuid(),
],
],
],
],
],
],
]);
$basePromotion->save();
Coupon::create([
'promotion_id' => $basePromotion->id(),
'code' => $couponCode,
'usage_limit' => 1,
'usage_limit_customer' => 1,
])->save();
The above was based on the results we saw in a JSON:API export after having created a sample Promotion through the UI (endpoint: commerce_promotion/commerce_promotion
). In those JSON:API exports, there IS a relationships
object that mentions order_types
, but the data
array is NEVER filled. Even when the Promotion is working fine (below), order_types
data
remains empty. That's what I'm calling a "bug" here.
With the above code, if you try to now redeem $couponCode, it won't work - saying the code is either invalid or expired or already redeemed. You can immediately "fix" this, and see the "silent"ness of order_types
by going into the Promotions UI and simply re-saving the Promotion. No need to change anything - just resave it. Doing so silently "fixes" the missing (from the API call above) order_types
, and the coupon code starts to work.
At this point, if you went back to the JSON:API export (endpoint: commerce_promotion/commerce_promotion
), the relationships
order_types
is still empty. I would have assumed, here, that we would see the order_types
being applied (which, in turn, would have told us "you need this when writing API stuff!").
To "fix" this from a ::create
standpoint, you just need to add:
$basePromotion = Promotion::create([
...
'order_types' => [
['target_id' => 'ORDER_TYPE_ID],
],
The code in question that requires order_types
is in promotion/src/Entity/
Promotion.php::available
:
if (!in_array($order->bundle(), $this->getOrderTypeIds())) {
return FALSE;
}
I don't currently know why the order_type
is not showing in a JSON:API request.
Active
2.0
Developer experience