Thursday, March 7, 2019

Sitecore commerce -Remove problem orders.


Query to remove problem orders:

DELETE FROM [XC.Commerce.SharedEnvironments].[dbo].[CommerceEntities]
WHERE [Id] in (SELECT[CommerceEntityId]
FROM [XC.Commerce.SharedEnvironments].[dbo].[CommerceLists]
where ListName = 'List-problemorders-ByDate')

and

DELETE FROM [XC.Commerce.SharedEnvironments].[dbo].[CommerceLists]
where ListName = 'List-problemorders-ByDate'

Saturday, March 2, 2019

Sitecore Commerce 8.2 -Problem orders for order reconciliation - Notification on email and slack.

Here are a few simple steps to configure a new minion which will run 12 hours and identify the problem statement orders
and will send an email to a configured email id and will send a slack message to a channels.

Step 1  - Configure Environment minion service variables.

    {
        "$type": "Sitecore.Commerce.Core.MinionPolicy, Sitecore.Commerce.Core",
        "WakeupInterval": "12:00:00",
        "ListToWatch": "TestProblemOrders",
        "FullyQualifiedName": "Feature.Commerce.Orders.Engine.Minions.TestProblemOrderReconcileMinion, Feature.Commerce.Orders.Engine",
        "ItemsPerBatch": 100,
        "SleepBetweenBatches": 500
      },
      {
        "$type": "Feature.Commerce.Orders.Engine.Policies.TestProblemOrderReconciliationPolicy, Feature.Commerce.Orders.Engine",
        "NotificationAlertPrefix": "Test Slack Channel Message",
        "ToAddresses": "tesetAddress@test.com",
        "NotificationAddresses": "testNotificationadress@test.com",
        "FromAddressEmailAddress": "fromaddress@test.com",
        "EnabledNotification": true
      },

 Step 2  - Configure Environment minion service variables.

Configure Project/Project.Commerce.Engine/Engine/ConfigureSitecore.cs to register the DI

services.AddTransient();
services.AddTransient();

Setup a class in commerce foundation to send the email notification.

Foundation/Commerce/Infrastructure/Engine/Foundation.Commerce.Infrastructure.Engine/Service/TestSendEmail.cs

Define an interface -

 public interface ISendEmail
    {
        void Send(SmtpClientSettings settings);
    }

Class implementation -

public class TestSendEmail : ISendEmail
    {
        /// 
        /// Sends the email.
        /// 
        /// The settings.
        public void Send(SmtpClientSettings settings)
        {
            if (settings?.EmailMessage == null)
            {
                return;
            }

            Task emailTask = Task.Run(async () => 
            {
              }

}


Define a policy for all smtp configurations.


 Step 3  - Define a new pipeline interface and class for notification.

using Foundation.Commerce.Infrastructure.Engine.Models;
using Sitecore.Commerce.Core;
using Sitecore.Framework.Pipelines;

namespace Foundation.Commerce.Infrastructure.Engine.Pipelines
{
    [PipelineDisplayName("Foundation.Commerce.Infrastructure.Smtp.Engine.Pipelines.ISendEmailPipeline")]
    public interface ISendEmailPipeline : IPipeline
    {
    }
}

using Foundation.Commerce.Infrastructure.Engine.Models;
using Microsoft.Extensions.Logging;
using Sitecore.Commerce.Core;
using Sitecore.Framework.Pipelines;

namespace Foundation.Commerce.Infrastructure.Engine.Pipelines
{
    public class SendEmailPipeline : CommercePipeline, ISendEmailPipeline
    {
        public SendEmailPipeline(IPipelineConfiguration configuration, ILoggerFactory loggerFactory)
        :base(configuration, loggerFactory)
        {
            
        }
    }
}

 Step 4  - Define pipeline block




namespace Foundation.Commerce.Infrastructure.Engine.Pipelines.Blocks
{

 public class TestSendNotificationBlock : PipelineBlock
    {
        private readonly ISendEmail _sendEmail;

        public SendNotificationBlock(ISendEmail sendEmail)
        {
            this._sendEmail = sendEmail;
        }


   public override async Task Run(NotificationMessage arg, CommercePipelineExecutionContext context)
        {
            if (arg == null || string.IsNullOrWhiteSpace(arg.Description) || string.IsNullOrWhiteSpace(arg.Subject))
            {
                // send email message
               return false;
            }

        }
    }
}

 Step 5  - Create a new minion class for order reconciliation  under /Feature.Commerce.Orders.Engine/Minions



namespace Feature.Commerce.Orders.Engine.Minions
{

    public class ProblemOrderReconcileMinion : Minion
    {
       private ISendEmailPipeline _sendEmailPipeline;

        public override void Initialize(IServiceProvider serviceProvider, ILogger logger, MinionPolicy policy,
            CommerceEnvironment environment,
            CommerceContext globalContext)
        {
            base.Initialize(serviceProvider, logger, policy, environment, globalContext);
            _sendEmailPipeline = serviceProvider.GetService();
        }

       public override async Task Run()
        {
           var ordersList = await this.GetListItems(this.Policy.ListToWatch, this.Policy.ItemsPerBatch);
           var orders = ordersList as Order[] ?? ordersList.ToArray();
            Logger.LogInformation($"[Problem Order Reconciliation Minion] Problem Orders {orders.Length}", this);

            if (!orders.Any())
            {
                Logger.LogWarning("No Problem Orders Found!");
                return new MinionRunResultsModel() { Name = Name, ItemsProcessed = 0};
            }

            Logger.LogInformation($"[Problem Order Reconciliation Minion] Triggering Send Email Pipeline", this);
            var isMailSent = await _sendEmailPipeline.Run(CreateEmailMessage(orders), this.MinionContext.GetPipelineContextOptions());

            var result = isMailSent ? "Successful" : "Failed";
            Logger.LogInformation($"[Problem Order Reconciliation Minion] Email Status {result}", this);
            return new MinionRunResultsModel() { Name = Name, ItemsProcessed = orders.Count()};
        }
}

that's it, it's very simple to configure the minion service in Sitecore commerce.