commercetools / commercetools-php-sdk

The e-commerce SDK from commercetools for PHP.
https://docs.commercetools.com/sdk/php-sdk#php-sdk-v1
MIT License
43 stars 22 forks source link

SetAttributeAction for a LocalizedEnumValue thorws 400 Bad Request. #487

Closed sadokmtir closed 5 years ago

sadokmtir commented 5 years ago

I have a localized enum with the key rubber. What I am trying to do is to set my custom attribute on the variant level to use that key from the enum. Unfortunately I am getting always 400 Bad Request. When I checked the field on the commerceTools frontend I can see that it has the value rubber as the Enumeration Key.

I try to set it this way:

ProductSetAttributeAction::ofSkuAndName($variantKey, $attributeName)>setValue($attributeKey); $attributeKey is rubber.

Response is:

{
    "statusCode": 400,
    "message": "The value '\"rubber\"' is not valid for field 'material'. ",
    "errors": [{
        "code": "InvalidField",
        "message": "The value '\"rubber\"' is not valid for field 'material'. ",
        "action": {
            "action": "setAttribute",
            "sku": "ABC12",
            "name": "material",
            "value": "rubber",
            "staged": true
        },
        "actionIndex": 2,
        "invalidValue": "rubber",
        "field": "material"
    }]
}
jenschude commented 5 years ago

I can't reproduce your issue. And the message is coming from the API so most likely you didn't defined the enum value to the product type of your product.

I used this test code to check if it's working:

public function testEnumAttributeWithSku()
{
    $productTypeDraft = ProductTypeDraft::ofNameAndDescription(
        'test-' . $this->getTestRun() . '-productType',
        'test-' . $this->getTestRun() . '-productType'
    )
        ->setAttributes(
            AttributeDefinitionCollection::of()
                ->add(
                    AttributeDefinition::of()
                        ->setName('testEnumField')
                        ->setLabel(LocalizedString::ofLangAndText('en', 'testEnumField'))
                        ->setIsRequired(false)
                        ->setAttributeConstraint('None')
                        ->setIsSearchable(false)
                        ->setType(EnumType::of()->setValues(EnumCollection::of()->add(Enum::of()->setKey("rubber")->setLabel("rubber"))))
                )
        )
    ;
    $request = ProductTypeCreateRequest::ofDraft($productTypeDraft);
    $response = $request->executeWithClient($this->getClient());
    $productType = $request->mapResponse($response);

    $draft = ProductDraft::ofTypeNameAndSlug(
        $productType->getReference(),
        LocalizedString::ofLangAndText('en', 'test-' . $this->getTestRun() . '-enumattribute'),
        LocalizedString::ofLangAndText('en', 'test-' . $this->getTestRun() . '-enumattribute')
    );
    $draft->setMasterVariant(ProductVariantDraft::of()->setSku($this->getTestRun()));
    $product = $this->createProduct($draft);

    $attributeValue = 'rubber';
    $request = ProductUpdateRequest::ofIdAndVersion($product->getId(), $product->getVersion())
        ->addAction(
            ProductSetAttributeAction::ofSkuAndName(
                $product->getMasterData()->getCurrent()->getMasterVariant()->getSku(),
                'testEnumField'
            )->setValue('rubber')
        )
    ;
    $response = $request->executeWithClient($this->getClient());
    $result = $request->mapResponse($response);
    $this->deleteRequest->setVersion($result->getVersion());

    $variant = $result->getMasterData()->getStaged()->getMasterVariant();
    $variant->getAttributes()->setAttributeDefinitions($productType->getAttributes());
    $this->assertInstanceOf(Product::class, $result);
    $this->assertSame(
        $attributeValue,
        $variant->getAttributes()->getByName('testEnumField')->getValueAsEnum()->getKey()
    );
    $this->assertNotSame($product->getVersion(), $result->getVersion());

    $this->deleteRequest->setVersion($result->getVersion());
}
sadokmtir commented 5 years ago

This is the way we create the localizedEnum in commerceTools:

  $action = ProductTypeAddLocalizedEnumValueAction::ofAttributeNameAndValue(
            $attributeName,
            LocalizedEnum::of()
                ->setKey($key)
                ->setLabel(
                    new LocalizedString(
                        [
                            $defaultCountryCode => $value,
                        ]
                    )
                )
        );

        $request  = ProductTypeUpdateByKeyRequest::ofKeyAndVersion($productType->getKey(), $productType->getVersion())
            ->addAction($action);
        $response = $this->client->execute($request);
jenschude commented 5 years ago

The same code works for me also with LocalizedEnums:

   $productTypeDraft = ProductTypeDraft::ofNameAndDescription(
        'test-' . $this->getTestRun() . '-productType',
        'test-' . $this->getTestRun() . '-productType'
    )
        ->setAttributes(
            AttributeDefinitionCollection::of()
                ->add(
                    AttributeDefinition::of()
                        ->setName('testLocalizedEnumField')
                        ->setLabel(LocalizedString::ofLangAndText('en', 'testLocalizedEnumField'))
                        ->setIsRequired(false)
                        ->setAttributeConstraint('None')
                        ->setIsSearchable(false)
                        ->setType(LocalizedEnumType::of()->setValues(
                            LocalizedEnumCollection::of()->add(
                                LocalizedEnum::of()->setKey("rubber")->setLabel(LocalizedString::ofLangAndText("en", "rubber"))
                            )
                        )
                    )
                )
        )
    ;

You must be missing this specific enum at the used product type. Please better ask support@commercetools.com as this issue is not directly related to the SDK itself.

sadokmtir commented 5 years ago

I figured out that the LocalizedEnum was created as SetType thats why it did not work when I tried to used as normal LocalizedEnum. Thank you for your feedback as well.