November Happy Hour will be moved to Thursday December 5th.

Custom properties on line items are not saved to PurchaseOrder when using SerializableCart

Vote:
 

Episerver: 11.8.0

Commerce: 12.2.0

I know this should have been fixed: https://world.episerver.com/support/Bug-list/bug/COM-4014 but I can't get it to work

Steps to reproduce

cart.GetAllLineItems().Single().Properties["Test"] = "my value";
_orderRepository.Save(cart);
var orderRef = _orderRepository.SaveAsPurchaseOrder(cart);
var purchaseOrder = _orderRepository.Load(orderRef.OrderGroupId);

var poValue = purchaseOrder.GetAllLineItems().Single().Properties["Test"];
// .Properties does not contain the "Test" entry :-(

Any hints?

#194641
Jun 27, 2018 9:43
Vote:
 

Just to touch base: Has your LineItem MetaClass been extended with the "Test" metafield?

#194642
Jun 27, 2018 9:53
Vote:
 

The LineItem MetaClass has not been altered - loving the serialized cart where that is not required

#194643
Jun 27, 2018 9:55
Vote:
 

Ok. That's probably the issue then :D

PurchaseOrders aren't serialized so you need to extend the classes anyway if you intend to convert serializable carts to purchase orders. It's described further here:

https://world.episerver.com/documentation/developer-guides/commerce/orders/serializable-carts/#Serializablecomponents (Under "Adding custom data" -> Note 1 & Note 2)

Try extending the LineItem MetaClass and see if that works.

#194644
Edited, Jun 27, 2018 9:59
Vote:
 

Thanks for quick diagnostic!

Is it posible to alter the LineItem MetaClass from an InitializationModule or the like? - I would hate to do it throgh the UI

#194645
Jun 27, 2018 10:04
Vote:
 

Because you ask "is it" - so the answer is yes.

You will need to load the MetaClass (MetaClass.Load) and check if it has the metafield or not (via metaClass.MetaFields), if it not, then create one (MetaField.Create), then add it to the MetaClass (MetaClass.AddField) 

I wrote about it somewhere ... 

#194646
Jun 27, 2018 10:15
Vote:
 

It's possible yes, I haven't done it specifically through an Initializable module but I have example code for creating the actual field:

        // For working with metafields I like to have their names as constants somewhere so there won't be any issues when calling for it. This is just an example:
        public class MyLineItemMetaFieldConstants 
        {
            public const string Test = "LineItemTest"; // usage would be LineItem.Properties[MyLineItemMetaFieldConstants.Test]
        }

        // Somewhere you'll add this
        public static void AddTestLineItemMetaField()
        {
            var metaClass = MetaClass.Load(CatalogContext.MetaDataContext, "LineItemEx");
            var currentFields = metaClass.GetUserMetaFields().ToList();

            var metaField = MetaField.Load(CatalogContext.MetaDataContext, MyLineItemMetaFieldConstants.Test) ??
                            MetaField.Create(
                                CatalogContext.MetaDataContext,
                                "Mediachase.Commerce.Orders.User.LineItem", // MetaNamespace (should be lineitem in your case)
                                MyLineItemMetaFieldConstants.Test, // name
                                MyLineItemMetaFieldConstants.Test, // FriendlyName
                                "Test field for testing purposes", // Description
                                MetaDataType.ShortString, // Database type
                                512, // Databae length
                                true, // nullable
                                false, // multi language value
                                false, // allow search
                                false); // is encrypted

            if (currentFields.All(x => x.Name != MyLineItemMetaFieldConstants.Test))
                metaClass.AddField(metaField);
        }

Edit: Oops, Quan had already answered. But oh well here's code example anyway. :D

#194648
Edited, Jun 27, 2018 10:28
Vote:
 

Thanks a bunch - it works like a charm*

I ended up with this

[ModuleDependency(typeof(InitializationModule))]
    public class OrderSystemInitializationModule : IConfigurableModule
    {
        public void Initialize(InitializationEngine context)
        {
            // if we 
            AddCustomPropertiesToLineItem();
        }

        public void Uninitialize(InitializationEngine context)
        {
        }

        public void ConfigureContainer(ServiceConfigurationContext context)
        {
        }

        private void AddCustomPropertiesToLineItem()
        {
            var fieldExists = MetaField.Load(CatalogContext.MetaDataContext, LineItemExtensions.VariantIdKey) != null;
            if (!fieldExists)
            {
                var newMetaField = MetaField.Create(
                    CatalogContext.MetaDataContext,
                    "Mediachase.Commerce.Orders.User.LineItem", // MetaNamespace
                    LineItemExtensions.VariantIdKey, // name
                    LineItemExtensions.VariantIdKey, // FriendlyName
                    "Holds the SapId of the line item", // Description
                    MetaDataType.ShortString, // Database type
                    50, // Databae length
                    true, // nullable
                    false, // multi language value
                    false, // allow search
                    false); // is encrypted

                var metaClass = MetaClass.Load(CatalogContext.MetaDataContext, "LineItemEx");
                var currentFields = metaClass.GetUserMetaFields().ToList();
                if (currentFields.All(x => x.Name != LineItemExtensions.VariantIdKey))
                    metaClass.AddField(newMetaField);
            }
        }
    }

*One small gotcha

It only works if the name og the meta field starts with a lower cased letter :-(

"test" works, but "Test" doesn't

[Pasting files is not allowed]

#194653
Edited, Jun 27, 2018 12:54
Vote:
 

I haven't experienced that. You should be able to have "Test" as a name. What error do you get?

Btw minor performance thing in your code, if the metaField != null you can just return right there and skip the step of loading the MetaClass. :D

#194654
Jun 27, 2018 13:08
Vote:
 

I get not error, just en empty property :-(

True about the perf thing - updated code above

#194655
Edited, Jun 27, 2018 13:11
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.