[PP-1] Order's Adjustment can't be normalized and serialized

Created on 14 October 2017, over 7 years ago
Updated 15 June 2023, almost 2 years ago

Problem/Motivation

Order's Adjustment can't be normalized, So the field adjustments can't been serialized
there is a core bug cause this, #2915705: TypedData 'Any' can't be normalized to array if it stores an object โ†’
the core will not recursive normalzie object,

But the resolution require that object itself saved to a 'any' type data must been normalizable or traversable

Proposed resolution

Make Adjustment been traversable

Remaining tasks

make Adjustment implement IteratorAggregate

User interface changes

API changes

Data model changes

๐Ÿ› Bug report
Status

Postponed

Version

2.0

Component

Order

Created by

๐Ÿ‡จ๐Ÿ‡ณChina lawxen

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia Akhil Babu Chengannur

    Thanks for the patch. Adjustment values are now getting displayed in API response after applying the latest patch from https://www.drupal.org/project/drupal/issues/2915705 โ†’ and then 2916252-66.patch.
    But there was a waring after applying 2916252-66.patch.
    Deprecated function: Return type of Drupal\commerce_order\Adjustment::getIterator() should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in include()
    Updating 2916252-66.patch to remove the warning.
    Change

      public function getIterator() {
        return new \ArrayIterator($this->toArray());
      }

    to

      public function getIterator(): \ArrayIterator {
        return new \ArrayIterator($this->toArray());
      }
  • ๐Ÿ‡จ๐Ÿ‡พCyprus alex.bukach

    It should be \Traversable, not \ArrayIterator.

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Agence Web CoherActio

    The last patch caused side-effects (e.g. price substract() method with adjustment).
    I ended up extending Drupal TypedDataNormalizer class to support Ajdustment normalizer

    namespace Drupal\my_module\Normalizer;
    
    use Drupal\commerce_order\Adjustment;
    use Drupal\Core\TypedData\TypedDataInterface;
    use Drupal\serialization\Normalizer\TypedDataNormalizer;
    
    class MyModuleAdjustmentNormalizer extends TypedDataNormalizer {
    
      /**
       * {@inheritdoc}
       */
      public function normalize($object, $format = NULL, array $context = []): array|string|int|float|bool|\ArrayObject|NULL {
        $this->addCacheableDependency($context, $object);
        $value = $object->getValue();
        // Support for stringable value objects: avoid numerous custom normalizers.
        if (is_object($value) && method_exists($value, '__toString')) {
          $value = (string) $value;
        }
        if ($value instanceof Adjustment) {
          $value = $value->toArray();
        }
        return $value;
      }
    }
    
  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    The attached patch works... However I don't think we can commit it as this means Commerce just provides a normalizer for the "Any" data type, which is used by other field types... which is a problem... But attaching the patch anyway..

  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    Perhaps we could provide our normalizer, only if the core one introduced in #2915705: TypedData 'Any' can't be normalized to array if it stores an object โ†’ doesn't exist?

  • Status changed to Needs review about 1 year ago
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update about 1 year ago
    794 pass
  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    Actually, let's go with this patch... Which provides the "Any" normalizer conditionally in case it is not defined by the serialization module.

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update about 1 year ago
    794 pass
  • Pipeline finished with Success
    about 1 year ago
    Total: 505s
    #184882
  • First commit to issue fork.
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update about 1 year ago
    CI error
  • Pipeline finished with Failed
    about 1 year ago
    Total: 491s
    #187226
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update about 1 year ago
    Unable to generate test groups
  • Pipeline finished with Success
    about 1 year ago
    Total: 521s
    #187258
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update about 1 year ago
    Unable to generate test groups
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update about 1 year ago
    Unable to generate test groups
  • Pipeline finished with Canceled
    about 1 year ago
    Total: 46s
    #187267
  • Pipeline finished with Success
    about 1 year ago
    Total: 490s
    #187268
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update 12 months ago
    794 pass, 2 fail
  • Pipeline finished with Failed
    12 months ago
    Total: 478s
    #190748
  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    We were missing the test group (added that). But also suddenly not sure about the fix, whenever I don't skip the test methods defined by the base class, there seems to be an issue with the denormalization of the adjustments field... Also... now extending getSupportedTypes() from the normalizer as the previous approach :

      /**
       * {@inheritdoc}
       */
      protected $supportedInterfaceOrClass = Any::class;
    

    is deprecated in D10.2. I'd need to double check when this change was introduced to see if we need ot raise the required core version... Since I'm not sure the issue is actually fixed... Putting this issue on hold for now.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States mrweiner

    @jsacksick re: #80, I can confirm that the patch in #77 fixes the issue for me on D10.3.0.

  • Pipeline finished with Skipped
    11 months ago
    #213298
  • ๐Ÿ‡ฎ๐Ÿ‡นItaly trickfun

    Patch #77 works fine with Drupal 10.3
    Thank you

  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    Last time I worked on the tests, they were failing, and can't remember why, so looks like the patch doesn't address all the problems...

  • ๐Ÿ‡ฎ๐Ÿ‡นItaly trickfun

    @jsacksick i have this patch too https://www.drupal.org/project/drupal/issues/3300404 ๐Ÿ“Œ Unserialize(): Passing null to parameter #1 ($data) of type string is deprecated in Drupal\Core\Entity\Sql\SqlContentEntityStorage Needs work

  • Pipeline finished with Failed
    10 months ago
    #240684
  • Pipeline finished with Success
    10 months ago
    #243638
  • Pipeline finished with Success
    10 months ago
    Total: 450s
    #243650
  • Pipeline finished with Success
    10 months ago
    Total: 453s
    #243658
  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    @tBKoT: Interesting approach, just wondering if this isn't a breaking change?
    Also, we might as well copy what was done in Commerce API. The Commerce API module defines an Adjustment data type as well as an AdjustmentDataDefinition definition class.

    The data definition class defines all the adjustment properties. This should help getting rid of the "value".

  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine tbkot

    @jsacksick I've tried to get rid of the "value" key but it seems that it is not possible without rewriting a lot of staff or removing the denormalization process in the test (it would fail in this case)

    The main thing is that JSON:API uses the field property definition as a foundation to generate the structure if we change it as a result all other things related to this field would be broken such as getAdjustments() etc. as those methods use "value" and I guess many other contrib/custom solutions may use this field like that.

    Another thing that can help is to define more properties with their own data types to set values for Label, Type, Amount, etc. I do not think it is the best way to resolve this.

    One more solution is to disable access to the main "adjustment" field for JSON:API as it is done in the "commerce_api" module and define a new computed field for it to show adjustment without the "value" key.

  • Pipeline finished with Success
    10 months ago
    Total: 546s
    #248022
  • Pipeline finished with Success
    9 months ago
    Total: 445s
    #275317
  • Pipeline finished with Skipped
    9 months ago
    #275682
  • ivnish Kazakhstan

    The patch from MR fix the WSOD. Looks like RTBC

  • Pipeline finished with Success
    8 months ago
    Total: 54s
    #303962
  • Pipeline finished with Success
    8 months ago
    Total: 55s
    #309519
  • Pipeline finished with Success
    7 months ago
    Total: 686s
    #336782
  • Pipeline finished with Success
    7 months ago
    Total: 1337s
    #336789
  • Pipeline finished with Success
    7 months ago
    Total: 762s
    #336801
  • Pipeline finished with Success
    7 months ago
    Total: 1505s
    #336807
  • Pipeline finished with Success
    7 months ago
    Total: 208s
    #336818
  • Pipeline finished with Success
    7 months ago
    Total: 155s
    #336828
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom alexpott ๐Ÿ‡ช๐Ÿ‡บ๐ŸŒ

    Need the patch for a D11 site.

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom alexpott ๐Ÿ‡ช๐Ÿ‡บ๐ŸŒ

    Ah we need return typehints...

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance goz

    #89 works great on Commerce 3.0

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance goz

    But we should also support denormalizer implementing DenormalizerInterface and adding denormalize method, so we can create order item with adjustment from jsonapi.

    
      /**
       * {@inheritdoc}
       */
      public function denormalize($data, $type, $format = NULL, array $context = []) {
        if (isset($context['field_type']) && 'commerce_adjustment' === $context['field_type']) {
          if (isset($data['amount'], $data['amount']['number'], $data['amount']['currency_code'])) {
            $data['amount'] = new Price($data['amount']['number'], $data['amount']['currency_code']);
          }
          return new Adjustment($data);
        }
    
        return $data;
      }
    
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance goz
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance goz

    #89 works with 3.0 but use previous fix based on "Any".
    MR add the adjustmentType which should be kept for 3.0

  • Pipeline finished with Failed
    3 months ago
    Total: 341s
    #440727
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance goz

    goz โ†’ changed the visibility of the branch 3.0.x to hidden.

  • Pipeline finished with Failed
    3 months ago
    Total: 510s
    #440760
  • Pipeline finished with Canceled
    3 months ago
    Total: 280s
    #442929
  • Pipeline finished with Failed
    3 months ago
    Total: 647s
    #442933
  • Pipeline finished with Success
    3 months ago
    Total: 755s
    #443035
  • Status changed to Needs work 23 days ago
  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    Do we actually need to declare each individual property like the following? The normalizer is on the value property, isn't that sufficient?
    The normalization still works without those... Or is that needed for setting adjustments though the API?

    $properties['type'] = DataDefinition::create('adjustment_property')
          ->setLabel(t('Type'))
          ->setComputed(TRUE);
    
        $properties['label'] = DataDefinition::create('adjustment_property')
          ->setLabel(t('Label'))
          ->setComputed(TRUE);
    
        $properties['amount'] = DataDefinition::create('adjustment_property')
          ->setLabel(t('Amount'))
          ->setComputed(TRUE);
    
        $properties['source_id'] = DataDefinition::create('adjustment_property')
          ->setLabel(t('Source ID'))
          ->setComputed(TRUE);
    
        $properties['percentage'] = DataDefinition::create('adjustment_property')
          ->setLabel(t('Amount'))
          ->setComputed(TRUE);
    
        $properties['included'] = DataDefinition::create('adjustment_property')
          ->setLabel(t('Included'))
          ->setComputed(TRUE);
    
        $properties['locked'] = DataDefinition::create('adjustment_property')
          ->setLabel(t('Locked'))
          ->setComputed(TRUE);
    

    Isn't it

  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    Ok removing the extra properties from the AdjustmentItem failed... But removing the AdjustmentPropertyDefinition worked... Wondering why it was added in the first place?

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States rhovland Oregon

    So on our site we're writing new adjustments through the API, not just updating existing ones so we need all of those extra properties to be able to set the characteristics of the adjustment.

  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    @rhovland: Does the current patch allow for that? (from the MR)? I'm considering merging it as it looks ready.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States rhovland Oregon

    I will update our patch on our test site and make sure the removal of AdjustmentPropertyDefinition didn't mess anything up.

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance goz

    With last patch, no error is thrown, i can list adjustments for orders and order items, but i cannot create them.

    GET /jsonapi/commerce_order/default?filter[drupal_internal__order_id]=3807'

    {
        "jsonapi": {
            "version": "1.0",
            "meta": {
                "links": {
                    "self": {
                        "href": "http://jsonapi.org/format/1.0/"
                    }
                }
            }
        },
        "data": [
            {
                "type": "commerce_order--default",
                "id": "ad15f584-05f7-43a8-bd55-ab18a4eaba2c",
                "links": {
    ...
                },
                "attributes": {
                    "drupal_internal__order_id": 3807,
                    "order_number": "3807",
    ...
                    "adjustments": [
                        {
                            "type": "shipping",
                            "label": "Expรฉdition",
                            "amount": {
                                "number": "4.95",
                                "currency_code": "EUR",
                                "formatted": "4,95 โ‚ฌ"
                            },
                            "percentage": null,
                            "source_id": "1058",
                            "included": false,
                            "locked": false
                        }
                    ],
                    "total_price": {
                        "number": "28.950000",
                        "currency_code": "EUR",
                        "formatted": "28,95 โ‚ฌ"
                    },
                    "total_paid": null,
                    "balance": {
                        "number": "28.950000",
                        "currency_code": "EUR",
                        "formatted": "28,95 โ‚ฌ"
                    },
                    "state": "completed",
                    "locked": false,
                    "created": "2025-03-14T08:13:38+00:00",
                    "changed": "2025-03-14T13:53:41+00:00",
                    "placed": "2025-03-14T13:53:41+00:00",
                    "completed": "2025-03-14T13:53:41+00:00",
                    "customer_comments": null,
                    "cart": false,
                    "checkout_step": "complete",
    ...
                },
                "relationships": {
    ...
                }
            }
        ],
    ...
    }
    

    But creating new order doesn't :

    {
        "data": {
            "type": "commerce_order_item--abonnement_single",
            "attributes": {
                                "title": "Abonnement individuel - 1 an",
                                "quantity": "1.00",
                                "unit_price": {
                                    "number": "15.000000",
                                    "currency_code": "EUR",
                                    "formatted": "15,00 โ‚ฌ"
                                },
                                "total_price": {
                                    "number": "15.000000",
                                    "currency_code": "EUR",
                                    "formatted": "15,00 โ‚ฌ"
                                },
                                "adjustments": [
                                    {
                                        "type": "tax",
                                        "label": "TVA",
                                        "amount": {
                                            "number": "0.31",
                                            "currency_code": "EUR"
                                        },
                                        "percentage": "0.021",
                                        "source_id": "france|0|0",
                                        "included": true
                                    }
                                ]
            },
            "relationships": {
                "uid": {
                    "data": {
                        "type": "user--user",
                        "id": "565a095e-d398-4ebb-9030-f877d9301601"
                    }
                },
                "order_id": {
                    "data": {
                        "type": "commerce_order--default",
                        "id": "f1fe4660-dba4-4c90-8c0e-4090310a1e78"
                    }
                },
                "store_id": {
                    "data": {
                        "type": "commerce_store--online",
                        "id": "1adc9d7c-c976-4951-9cd4-38413b150a51"
                    }
                },
                "purchased_entity": {
                    "data": {
                        "type": "commerce_product_variation--abonnement_single",
                        "id": "e12569c7-24a4-4a5c-844f-d67ea1e01a21"
                    }
                }
    
            }
        }
    }
    

    Result :

    {
        "jsonapi": {
            "version": "1.0",
            "meta": {
                "links": {
                    "self": {
                        "href": "http://jsonapi.org/format/1.0/"
                    }
                }
            }
        },
        "data": {
            "type": "commerce_order_item--abonnement_single",
            "id": "cea7ce7c-84c2-4154-85b6-e65c87bf233c",
            "links": {
    ...
            },
            "attributes": {
                "drupal_internal__order_item_id": 5932,
                "title": "Abonnement individuel - 1 an",
                "overridden_title": false,
                "quantity": "1",
                "unit_price": {
                    "number": "15.000000",
                    "currency_code": "EUR",
                    "formatted": "15,00 โ‚ฌ"
                },
                "overridden_unit_price": false,
                "total_price": {
                    "number": "15.00",
                    "currency_code": "EUR",
                    "formatted": "15,00 โ‚ฌ"
                },
                "adjustments": [],
                "uses_legacy_adjustments": false,
                "data": null,
                "locked": false,
                "created": "2025-05-16T10:34:03+00:00",
                "changed": "2025-05-16T10:34:03+00:00"
            },
    ..
    }
    

    Same thing creating order_item.

  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    @goz: What we don't see in your response is whether the order is a draft order? IF it is a draft order then on order save, the adjustment will be cleared by the OrderRefresh service right? So that is probably expected? You'd need to try on a non draft order.

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance goz

    My bad, you are right, adjustments are cleared and recalculated. I forgot that. Checked again and everything is fine

  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    So RTBC then? Would be great to finally close this... I think this is ready! Would appreciate an RTBC.

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance goz

    Let's do it !
    Thanks

  • Pipeline finished with Skipped
    16 days ago
    #499032
  • Pipeline finished with Skipped
    16 days ago
    #499035
  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    Merged! ๐ŸŽ‰! Thanks everyone!!

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States rhovland Oregon

    So far we have not been able to use PATCH to replace adjustments. They go poof with no error returned. This is on non-draft orders.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States rhovland Oregon

    If I try to send a patch request to https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e...

    With JSON

    {
        "data":{
            "type": "commerce_order--default",
            "id": "ab42ab1c-b21f-4da2-9e9b-82213e622e59",
            "attributes": {
                "adjustments": [
                    {
                        "type": "shipping",
                        "label": "Shipping",
                        "amount": {
                            "number": "126.940000",
                            "currency_code": "USD"
                        },
                        "percentage": null,
                        "source_id": "209676",
                        "included": false,
                        "locked": false
                    }
                ]
            }
        }
    }
    

    I get the response

    {
        "jsonapi": {
            "version": "1.0",
            "meta": {
                "links": {
                    "self": {
                        "href": "http://jsonapi.org/format/1.0/"
                    }
                }
            }
        },
        "data": {
            "type": "commerce_order--default",
            "id": "ab42ab1c-b21f-4da2-9e9b-82213e622e59",
            "links": {
                "self": {
                    "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59"
                }
            },
            "attributes": {
                "drupal_internal__order_id": 289391,
                "order_number": "289391",
                "version": 15,
                "mail": "redacted@example.com",
                "ip_address": "208.56.233.218",
                "adjustments": [],
                "total_price": {
                    "number": "226.22",
                    "currency_code": "USD",
                    "formatted": "$226.22"
                },
                "total_paid": {
                    "number": "253.160000",
                    "currency_code": "USD",
                    "formatted": "$253.16"
                },
                "balance": {
                    "number": "-26.94",
                    "currency_code": "USD",
                    "formatted": "-$26.94"
                },
                "state": "shipped",
                "data": {
                    "paid_event_dispatched": true
                },
                "locked": false,
                "created": "2024-12-16T21:19:32+00:00",
                "changed": "2025-05-16T20:19:03+00:00",
                "placed": "2024-12-16T21:28:24+00:00",
                "completed": null,
                "customer_comments": null,
                "cart": false,
                "checkout_step": null,
                "field_customer_comments": null,
                "field_customer_motorcycles": [],
                "field_newsletter": false
            },
            "relationships": {
                "commerce_order_type": {
                    "data": null,
                    "links": {
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/commerce_order_type"
                        }
                    }
                },
                "store_id": {
                    "data": null,
                    "links": {
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/store_id"
                        }
                    }
                },
                "uid": {
                    "data": {
                        "type": "user--user",
                        "id": "e369285a-16a1-4817-baa5-b4848443a28a",
                        "meta": {
                            "drupal_internal__target_id": 29634
                        }
                    },
                    "links": {
                        "related": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/uid"
                        },
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/uid"
                        }
                    }
                },
                "billing_profile": {
                    "data": {
                        "type": "profile--customer",
                        "id": "2cfa79d0-3d74-4c99-bff2-3a26ee115a21",
                        "meta": {
                            "target_revision_id": 363841,
                            "drupal_internal__target_id": 364046
                        }
                    },
                    "links": {
                        "related": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/billing_profile"
                        },
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/billing_profile"
                        }
                    }
                },
                "order_items": {
                    "data": [
                        {
                            "type": "commerce_order_item--parts",
                            "id": "55aaae86-e1dc-4c22-943e-7503deef65b7",
                            "meta": {
                                "drupal_internal__target_id": 1073893
                            }
                        }
                    ],
                    "links": {
                        "related": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/order_items"
                        },
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/order_items"
                        }
                    }
                },
                "checkout_flow": {
                    "data": null,
                    "links": {
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/checkout_flow"
                        }
                    }
                },
                "commerce_giftcards": {
                    "data": [],
                    "links": {
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/commerce_giftcards"
                        }
                    }
                },
                "payment_gateway": {
                    "data": null,
                    "links": {
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/payment_gateway"
                        }
                    }
                },
                "payment_method": {
                    "data": null,
                    "links": {
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/payment_method"
                        }
                    }
                },
                "coupons": {
                    "data": [],
                    "links": {
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/coupons"
                        }
                    }
                },
                "shipments": {
                    "data": [
                        {
                            "type": "commerce_shipment--default",
                            "id": "86c32de5-5cd6-4542-abaf-23065e0458a1",
                            "meta": {
                                "drupal_internal__target_id": 209706
                            }
                        }
                    ],
                    "links": {
                        "related": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/shipments"
                        },
                        "self": {
                            "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59/relationships/shipments"
                        }
                    }
                }
            }
        },
        "links": {
            "self": {
                "href": "https://example.com/jsonapi/commerce_order/default/ab42ab1c-b21f-4da2-9e9b-82213e622e59"
            }
        }
    }
    

    The adjustments are just empty.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States rhovland Oregon

    Ok so after combing through things, we were using #72 ๐Ÿ› [PP-1] Order's Adjustment can't be normalized and serialized Postponed plus the core Any normalizer patch and it was working.

    The issue seems to be the final commit never implemented a denormalizer so that PATCH operations can work. The patch we were using had one. Kinda.

    diff --git a/modules/order/src/Plugin/Field/FieldType/AdjustmentItem.php b/modules/order/src/Plugin/Field/FieldType/AdjustmentItem.php
    index 81ae6c90..cbc96972 100644
    --- a/modules/order/src/Plugin/Field/FieldType/AdjustmentItem.php
    +++ b/modules/order/src/Plugin/Field/FieldType/AdjustmentItem.php
    @@ -3,6 +3,7 @@
     namespace Drupal\commerce_order\Plugin\Field\FieldType;
    
     use Drupal\commerce_order\Adjustment;
    +use Drupal\commerce_price\Price;
     use Drupal\Core\Field\FieldItemBase;
     use Drupal\Core\Field\FieldStorageDefinitionInterface;
     use Drupal\Core\TypedData\DataDefinition;
    @@ -48,6 +49,11 @@ class AdjustmentItem extends FieldItemBase {
           // The property definition causes the adjustment to be in 'value' key.
           $values = reset($values);
         }
    +    // Used for denormalization.
    +    if (is_array($values)) {
    +      $values['amount'] = new Price($values['amount']['number'], $values['amount']['currency_code']);
    +      $values = new Adjustment($values);
    +    }
         if (!$values instanceof Adjustment) {
           $values = NULL;
         }
    

    So as committed this lets you read adjustments via API but not write them.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States rhovland Oregon

    @goz You got this to successfully write order adjustments? Do you have commerce_api installed?

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024