top of page
Hina Garg

Extend order schema via code in Sitecore Commerce 9.3

I am recently working on a commerce piece which has a requirement of extending existing order EntityView schema in Sitecore Commerce 9.3. Through this blog I hope to provide some information to Sitecore commerce developers who might work on similar tasks in future.

Approach:

1. Add a Component class to declare all the fields that need to be added to the order schema.

Example Code:

public class ExampleOrderComponent : Component
    {
        [Display(Name = "Example ID")]
        public int ExampleID { get; set; } = 0;

        [Display(Name = "Shipping Amount")]
        public decimal ShippingAmount { get; set; } = 0.0m;

        [Display(Name = "Express Amount")]
        public decimal ExpressAmount { get; set; } = 0.0m;

    }

2. Add a new view policy to declare view display properties.


Example Code:


public class ExampleOrderViewsPolicy : Policy
    {
        public string ExampleSettings { get; set; } ="ExampleSettings";
        public string ExampleDisplayName { get; set; } = "Example Order"
    }

3. Add a new constants class.


Example Code:


public static class ExampleSchemaConstants
    {
        public static class Pipelines
        {
            public static class Blocks
            {              
                public const string GetExampleOrderViewBlock = "Example.orders.block.getexampleorderviewblock";     
                    
            }
        }

4. Add a new EntityView class to extend and populate the new schema.


Example Code:


namespace Plugin.ExampleProject.Schema.Orders.Pipelines.Blocks.EntityViews
{
    [PipelineDisplayName(OrderSchemaConstants.Pipelines.Blocks.GetExampleOrderViewBlock)]
    public class GetExampleOrderViewBlock : PipelineBlock<EntityView, EntityView, CommercePipelineExecutionContext>
    {
        private readonly ViewCommander _viewCommander;

        public GetExampleOrderViewBlock(ViewCommander viewCommander)
        {
            this._viewCommander = viewCommander;
        }

        public override Task<EntityView> Run(EntityView entityView, CommercePipelineExecutionContext context)
        {
            Condition.Requires(entityView).IsNotNull($"{Name}: The argument cannot be null.");
            var policy = context.GetPolicy<KnownOrderViewsPolicy>();

            EntityViewArgument request = context.CommerceContext.GetObject<EntityViewArgument>();

            if (string.IsNullOrEmpty(request?.ViewName) || !request.ViewName.Equals(policy.Master, StringComparison.OrdinalIgnoreCase))
            {
                return Task.FromResult(entityView);
            }

            // Only proceed if the current entity is an order
            if (!(request.Entity is Order) || !string.IsNullOrEmpty(request.ForAction))
            {
                return Task.FromResult(entityView);
            }
            var order = request.Entity as Order;
            var exampleOrderComponent = order.GetComponent<ExamplOrderComponent>();
            var targetView = entityView;

            if (request.ViewName == context.GetPolicy<KnownOrderViewsPolicy>().Master)
            {
                var view = new EntityView
                {
                    Name = context.GetPolicy<ExampleOrderViewsPolicy>().ExampleSettings,
                    DisplayName = context.GetPolicy<ExampleOrderViewsPolicy>().ExampleDisplayName,
                    EntityId = entityView.EntityId,
                    ItemId = order.Id,
                    EntityVersion = entityView.EntityVersion
                };
                entityView.ChildViews.Add(view);
                targetView = view;

                // Invoke the method.
                AddPropertiesToView(targetView, exampleOrderComponent);
            }
            return Task.FromResult(entityView);
        }

        /// <summary>
        /// Extends the master view for orders.
        /// </summary>
        /// <param name="entityView"></param>
        /// <param name="exampleOrderComponent"></param>
        private void AddPropertiesToView(EntityView entityView, ExampleOrderComponent exampleOrderComponent)
        {
            foreach (PropertyInfo prop in exampleOrderComponent.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly))
            {
                entityView.Properties.Add(new ViewProperty()
                {
                    Name = prop.Name,
                    RawValue = prop.GetValue(exampleOrderComponent),
                    IsReadOnly = true,
                    IsRequired = true,
                    DisplayName = exampleOrderComponent.GetDisplayName(prop.Name)
                });
            }
            
        }
    }
}

Below helper method is invoked in above code.
public static class AnnotationExtensionMethods
    {
        public static string GetDisplayName(this object instance, string propertyName)
        {
            var attrType = typeof(DisplayAttribute);
            var property = instance.GetType().GetProperty(propertyName);
            var displayAttributes = (DisplayAttribute)property.GetCustomAttributes(attrType, false).First();

            if (displayAttributes == null)
                return propertyName;
            else
                return displayAttributes.Name;
        }
    }
 

5. Lastly, Add the newly created block to IGetEntityViewPipeline


public void ConfigureServices(IServiceCollection services)
        {
            var assembly = Assembly.GetExecutingAssembly();
            services.RegisterAllPipelineBlocks(assembly);
            services.RegisterAllCommands(assembly);

            services.Sitecore().Pipelines(config =>
                config
                    .ConfigurePipeline<IGetEntityViewPipeline>(c =>
                    {
                        c.Add<GetExampleOrderViewBlock>()
                        .After<GetOrdersDashboardViewBlock>();

                    })                

            );
        }

The coding journey with Sitecore Experience Commerce has been very interesting so far and I am really enjoying working on this platform. Happy Coding!!

97 views0 comments

Recent Posts

See All

Comments


bottom of page