Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Claudiu Bria 34 posts 146 karma points
    Mar 09, 2017 @ 18:54
    Claudiu Bria
    0

    OrderConfirmation general trigger

    Hi Rusty,

    I'm trying to have the following code in my own UmbracoEventHandler.cs:

       public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            OrderService.StatusChanged += OrderServiceStatusChanged;
            ShipmentService.StatusChanged += ShipmentServiceStatusChanged;
        }
    
        private void OrderServiceStatusChanged(IOrderService sender, StatusChangeEventArgs<IOrder> e)
        {
            var validKeys = new[]
                            {
                                Merchello.Core.Constants.OrderStatus.Fulfilled
                            };
    
            foreach (var order in e.StatusChangedEntities)
            {
                if (!validKeys.Contains(order.OrderStatus.Key)) continue;
    
                LogHelper.Info<UmbracoEventHandler>(string.Format("Raising notification trigger for order no. {0}", order.OrderNumber));
    
                Notification.Trigger("OrderConfirmation", order, Merchello.Core.Observation.Topic.Notifications);
            }
        }
    
        /// <summary>
        /// Example shipment shipped / delivered notification handler
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The <see cref="StatusChangeEventArgs{IShipment}"/>
        /// </param>
        private void ShipmentServiceStatusChanged(IShipmentService sender, StatusChangeEventArgs<IShipment> e)
        {
            var validKeys = new[]
                            {
                                Merchello.Core.Constants.ShipmentStatus.Delivered,
                                Merchello.Core.Constants.ShipmentStatus.Shipped
                            };
    
            foreach (var shipment in e.StatusChangedEntities)
            {
                if (!validKeys.Contains(shipment.ShipmentStatus.Key)) continue;
    
                LogHelper.Info<UmbracoEventHandler>(string.Format("Raising notification trigger for shippment no. {0}", shipment.ShipmentNumber));
    
                Notification.Trigger("OrderShipped", shipment, Merchello.Core.Observation.Topic.Notifications);
            }
        }
    

    The "OrderShipped" trigger works fine from both webshop interface and from my API code when changing the shipment status. The "OrderConfirmation" on the other hand does not work, the second parameter there, namely my order object does not comply as an accepted type internally, the code there requires only an IPaymentResult type of object, so how can i still get a similar implementation of the OrderConfirmation trigger (that could be triggered also from the web interface on the OrderStatus change to Fulfilled) in my UmbracoEventHandler please ? What do I miss here please ?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Mar 09, 2017 @ 22:18
    Rusty Swayne
    100

    Hey Claudia - the "OrderConfirmation" trigger alias is pretty misleading and is a remnant of really early versions of Merchello. The alias should really be "PaymentConfirmation" or "SaleComplete" since it has nothing to do with the order but rather a successful payment success - which is why the trigger expects an IPaymentResult.

    This is the line that is throwing when you pass an IOrder: https://github.com/Merchello/Merchello/blob/merchello-dev/src/Merchello.Core/Observation/TriggerBase.cs#L63

    The trigger you are calling is: https://github.com/Merchello/Merchello/blob/merchello-dev/src/Merchello.Core/Gateways/Notification/Triggering/OrderConfirmationTrigger.cs#L19 (Notice the attribute with the "OrderConfirmation") - which as you noticed is called by payment provider after an authorize or authorize-capture.

    The easiest way will be to introduce your own trigger and monitor ... something like:

    /// <summary>
    /// Represents a notification model for order fulfillment notifications.
    /// </summary>
    public interface IOrderFulfilledNotifyModel : INotifyModel
    {
        /// <summary>
        /// Gets or sets the invoice.
        /// </summary>
        IInvoice Invoice { get; set; }
    
        /// <summary>
        /// Gets or sets the order.
        /// </summary>
        IOrder Order { get; set; }
    
        /// <summary>
        /// Gets or sets the shipments.
        /// </summary>
        IEnumerable<IShipment> Shipments { get; set; }
    }
    

    The model:

        /// <inheritdoc/>
    internal class OrderFulfilledNotifyModel : IOrderFulfilledNotifyModel
    {
        /// <inheritdoc/>
        public IInvoice Invoice { get; set; }
    
        /// <inheritdoc/>
        public IOrder Order { get; set; }
    
        /// <inheritdoc/>
        public IEnumerable<IShipment> Shipments { get; set; }
    
        /// <summary>
        /// Gets or sets the contacts.
        /// </summary>
        public string[] Contacts { get; set; }
    }
    

    The trigger class. Notice the TriggerForAttribute ... the "OrderFulfilled" can be whatever you want it to be.

     /// <summary>
    /// A trigger for order fulfilled.
    /// </summary>
    [TriggerFor("OrderFulfilled", Topic.Notifications)]
    public class OrderFulfilledTrigger : NotificationTriggerBase<IOrder, IOrderFulfilledNotifyModel>
    {
        /// <summary>
        /// Value to pass to the notification monitors
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="contacts">
        /// An additional list of contacts
        /// </param>
        protected override void Notify(IOrder model, IEnumerable<string> contacts)
        {
            var invoice = model.Invoice();
            var shipments = new List<IShipment>();
            foreach (var o in invoice.Orders)
            {
                shipments.AddRange(o.Shipments());
            }
    
            var billingContact = invoice.GetBillingAddress().Email;
    
            var contactList = contacts?.ToList() ?? new List<string>();
    
            if (!billingContact.IsNullOrWhiteSpace()) contactList.Add(billingContact);
    
            var notifyModel = new OrderFulfilledNotifyModel
            {
                Invoice = invoice,
                Order = model,
                Shipments = shipments,
                Contacts = contactList.ToArray()
            };
    
            NotifyMonitors(notifyModel);
        }
    }
    

    The monitor for the trigger.

    The MonitorForAttribute parameters

    • Newly generated GUID
    • typeof([Must be the type of your trigger)
    • The text is what displays in the back office - yep, I know it's not localized =) ... still a todo
    • The final arg just leave true - use the back office code editor (for razor template)

      [MonitorFor("D5F6A745-4687-4FBF-92D5-AB193354C3BD", typeof(OrderFulfilledTrigger), "Order Fulfilled (Razor)", true)]
      public class RazorOrderFulfilledNotifyMonitor : RazorMonitorBase<IOrderFulfilledNotifyModel>
      {
      
      
      
       public RazorOrderFulfilledNotifyMonitor(INotificationContext notificationContext)
         : base(notificationContext)
       {
       }
      
      }
  • Cory Colt 34 posts 130 karma points
    Mar 15, 2017 @ 20:52
    Cory Colt
    0

    Rusty,

    I tried to follow this, but the Order Fulfilled Notification is still not being sent out. I'm not sure if I'm even doing this correctly, but I have created all of the classes you mentioned above and put them in the root of my solution for now, see screenshot below: enter image description here

    When I create the RazorOrderFulfilledNotifyMonitor I'm not sure where you're getting the GUID from in the MonitorFor attribute, so I looked in the database and there is a table called merchNotificationMessage and I used the GUID in the pk column, see screenshot: enter image description here

    [MonitorFor("21F25E24-0654-4C3D-A00E-39EEEC6F00F9", typeof(OrderFulfilledTrigger), "Order FulFilled (Razor)", true)]
    public class RazorOrderFulfilledNotifyMonitor : RazorMonitorBase<IOrderFulfilledNotifyModel>
    {
        public RazorOrderFulfilledNotifyMonitor(INotificationContext notificationContext) : base(notificationContext)
        {
    
        }
    }
    

    What am I missing? This has been very frustrating to get this notification working and I'm dead in the water until it is working correctly. Any help would be greatly appreciated!

  • Claudiu Bria 34 posts 146 karma points
    Mar 16, 2017 @ 08:09
    Claudiu Bria
    0

    Cory, about the MonitorFor GUID value, as I understand, anyone please correct me if I'm wrong, that one there is a completely new unique value (to be used by audits and such), so I use https://www.guidgenerator.com/ to get one.

  • Claudiu Bria 34 posts 146 karma points
    Mar 16, 2017 @ 10:48
    Claudiu Bria
    0

    Thank you Rusty, I got your guidelines, very helpful, thanks a lot !!!

    Instead of going forward with the OrderFulfilled, I decided to use only the already plugged event of ShipmentStatusChanged for the OrderShipped event that works on the web out of the box.

    Now, I created a new notification for CustomerCreated event:

    CustomerCreated

    ICustomerResultNotifyModel.cs:

        using Merchello.Core.Models.MonitorModels;
        using Umbraco.Core.Models;
    
        namespace AjourCms.Ajour.Models.MonitorModels
        {
            using Merchello.Core.Models;
    
            /// <summary>
            /// The CustomerResult interface.
            /// </summary>
            public interface ICustomerResultNotifyModel : INotifyModel
            {
                /// <summary>
                /// Gets or sets the customer.
                /// </summary>
                /// <value>
                /// The customer.
                /// </value>
                ICustomer Customer { get; set;  }
    
                IMember Member { get; set; }
            }
    
    }
    

    CustomerResultNotifyModel.cs:

    using Merchello.Core.Models;
    using Merchello.Core.Models.MonitorModels;
    using Umbraco.Core.Models;
    
    namespace AjourCms.Ajour.Models.MonitorModels
    {
        /// <summary>
        /// Represents a CustomerResultModel
        /// </summary>
        internal class CustomerResultNotifyModel : NotifyModelBase, ICustomerResultNotifyModel
        {
            /// <summary>
            /// Gets or sets the customer.
            /// </summary>
            /// <value>
            /// The customer.
            /// </value>
            public ICustomer Customer { get; set; }         
    
            public IMember Member { get; set; }
    
        }
    }
    

    Then the triggering, CustomerResultNotifyModelFactory.cs:

    using AjourCms.Ajour.Models.MonitorModels;
    using Merchello.Core;
    using Umbraco.Core.Services;
    
    namespace AjourCms.Ajour.Gateways.Notification.Triggering
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
    
        using Merchello.Core.Models;
        using Merchello.Core.Models.MonitorModels;
        using Merchello.Core.Services;
    
        using Umbraco.Core;
    
        /// <summary>
        /// The order shipped trigger helper.
        /// </summary>
        /// <remarks>
        /// http://issues.merchello.com/youtrack/issue/M-532
        /// </remarks>
        internal class CustomerResultNotifyModelFactory
        {
            /// <summary>
            /// The <see cref="ICustomerService"/>.
            /// </summary>
            private readonly ICustomerService _customerService;
    
            /// <summary>
            /// The <see cref="IMemberService"/>.
            /// </summary>
            private readonly IMemberService _memberService;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="CustomerResultNotifyModelFactory"/> class.
            /// </summary>
            public CustomerResultNotifyModelFactory()
                : this(MerchelloContext.Current)
            {
            }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="CustomerResultNotifyModelFactory"/> class.
            /// </summary>
            /// <param name="merchelloContext">
            /// The <see cref="IMerchelloContext"/>.
            /// </param>
            public CustomerResultNotifyModelFactory(IMerchelloContext merchelloContext)
            {
                Mandate.ParameterNotNull(merchelloContext, "merchelloContext");
    
                _customerService = merchelloContext.Services.CustomerService;
                _memberService = ApplicationContext.Current.Services.MemberService;
            }
    
            /// <summary>
            /// The build.
            /// </summary>
            /// <param name="customer">
            /// The customer.
            /// </param>
            /// <param name="contacts">
            /// The collection of contact addresses
            /// </param>
            /// <returns>
            /// The <see cref="ICustomerResultNotifyModel"/>.
            /// </returns>
            public ICustomerResultNotifyModel Build(ICustomer customer, IEnumerable<string> contacts)
            {
                var notifyModel = new CustomerResultNotifyModel()
                                      {
                                          Customer = customer,
                                          Contacts = contacts == null ? new string[] { } : contacts.ToArray()
                                        };
    
                var member = _memberService.GetByEmail(customer.Email);
    
                notifyModel.Member = member;
    
                return notifyModel;
            }
        }
    }
    

    and CustomerCreatedTrigger.cs:

    using AjourCms.Ajour.Models.MonitorModels;
    using Merchello.Core.Gateways.Notification.Triggering;
    
    namespace AjourCms.Ajour.Gateways.Notification.Triggering
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
    
        using Merchello.Core.Models;
        using Merchello.Core.Models.MonitorModels;
        using Merchello.Core.Observation;
    
        /// <summary>            
        /// Represents and CustomerCreatedTrigger
        /// </summary>
        [TriggerFor("CustomerCreated", Topic.Notifications)]
        public class CustomerCreatedTrigger : NotificationTriggerBase<ICustomer, ICustomerResultNotifyModel>
        {
            /// <summary>
            /// The <see cref="CustomerResultNotifyModelFactory"/>.
            /// </summary>
            private readonly Lazy<CustomerResultNotifyModelFactory> _factory = new Lazy<CustomerResultNotifyModelFactory>(() => new CustomerResultNotifyModelFactory()); 
    
            /// <summary>
            /// Value to pass to the notification monitors
            /// </summary>
            /// <param name="model">
            /// The model.
            /// </param>
            /// <param name="contacts">
            /// An additional list of contacts
            /// </param>
            protected override void Notify(ICustomer model, IEnumerable<string> contacts)
            {
                if (model == null) return;
    
                var notifyModel = _factory.Value.Build(model, contacts);
    
                NotifyMonitors(notifyModel);
            }
        }
    }
    

    Then the monitors, CustomerCreatedMonitor.cs:

    using Merchello.Core.Formatters;
    using Merchello.Core.Gateways.Notification;
    using Merchello.Core.Gateways.Notification.Monitors;
    
    namespace AjourCms.Ajour.Gateways.Notification.Monitors
    {
        using System.Linq;
        using Models.MonitorModels;
        using Merchello.Core.Observation;
        using Triggering;
    
        /// <summary>
        /// Represents a customer created monitor
        /// </summary>
        [MonitorFor("6ABE7A1C-FB5E-4A2D-9778-1D862F524F15", typeof(CustomerCreatedTrigger), "Customer Created", true)]
        public class CustomerCreatedMonitor : NotificationMonitorBase<ICustomerResultNotifyModel>
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="CustomerCreatedMonitor"/> class.
            /// </summary>
            /// <param name="notificationContext">
            /// The notification context.
            /// </param>
            public CustomerCreatedMonitor(INotificationContext notificationContext)
                : base(notificationContext)
            {            
            }
    
            /// <summary>
            /// Trigger call to notifify the monitor of a change
            /// </summary>
            /// <param name="value">
            /// The model to be used by the monitor
            /// </param>
            public override void OnNext(ICustomerResultNotifyModel value)
            {
                if (!Messages.Any()) return;
    
                var formatter = new DefaultFormatter();
    
                // Add the replaceable patterns 
                formatter.Format(value.Customer.Email);
    
                foreach (var message in Messages)
                {
                    if (message.SendToCustomer)
                    {
                        // add the additional contacts to the recipients list
                        if (!message.Recipients.EndsWith(";")) 
                            message.Recipients += ";";      
    
                        if (message.Recipients[0] == ';')
                            message.Recipients = message.Recipients.TrimStart(';');
    
                        var email = value.Customer.Email ?? value.Member.Email;
                        message.Recipients = string.Format("{0}{1}", message.Recipients, string.Join(";", email));
                    }            
    
                    // send the message
                    NotificationContext.Send(message, formatter);
                }
            }
        }
    }
    

    and RazorCustomerCreatedMonitor.cs:

    using AjourCms.Ajour.Gateways.Notification.Triggering;
    using AjourCms.Ajour.Models.MonitorModels;
    using Merchello.Web.Workflow.Notification.Monitor;
    
    namespace AjourCms.Ajour.Gateways.Notification.Monitors
    {
        using Merchello.Core.Gateways.Notification;
        using Merchello.Core.Observation;
    
        /// <summary>
        /// A razor based customer created monitor.
        /// </summary>
        [MonitorFor("7AADB8C2-0AE9-44F8-B1C1-8AC009C0E190", typeof(CustomerCreatedTrigger), "Customer Created (Razor)", true)]
        public class RazorCustomerCreatedMonitor : RazorMonitorBase<ICustomerResultNotifyModel>
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="RazorCustomerCreatedMonitor"/> class.
            /// </summary>
            /// <param name="notificationContext">
            /// The notification context.
            /// </param>
            public RazorCustomerCreatedMonitor(INotificationContext notificationContext)
                : base(notificationContext)
            {
            }
        }
    }
    

    Maybe you could tell me how to make this triggerable from the web at the moment when a new Customer is created, but for the moment I'm doing this manually thru the code in my API:

    /// <summary>
    /// Gets the <see cref="NewMemberModelFactory{TModel}"/>.
    /// </summary>
    private NewMemberModelFactory<NewMemberModel> NewMemberModelFactory { get; set; }
    
    [HttpGet]
    public HttpResponseMessage CreateCustomer(string loginName, string firstName, string lastName, string email, string password, string addressName = null, string addressAddress1 = null,
        string addressAddress2 = null, string addressOrganization = null, string addressLocality = null, string addressRegion = null, string addressPhone = null, string addressPostalCode = null,
        string addressCountryCode = null, string ajourLicenceKey = null)
    {
        var logData = new ExtendedLoggerData();
        logData.AddCategory("Merchello");
        logData.AddCategory("AjourCMSApi");
    
        if (string.IsNullOrEmpty(ajourLicenceKey))
        {
            ajourLicenceKey = WebAjourAppSettingsHelper.DefaultTrialLicenceKey;
        }
    
        var createdCustomer = new CreateCustomerResponse();
    
        Mandate.ParameterNotNullOrEmpty(loginName, "loginName");
        Mandate.ParameterNotNullOrEmpty(firstName, "firstName");
        Mandate.ParameterNotNullOrEmpty(lastName, "lastName");
        Mandate.ParameterNotNullOrEmpty(email, "email");
        Mandate.ParameterNotNullOrEmpty(password, "password");
    
        var merchelloServices = MerchelloContext.Current.Services;
        var customerService = merchelloServices.CustomerService;
        var existingCustomer = customerService.GetByLoginName(loginName);
        if (existingCustomer != null)
        {
            throw new Exception("Customer already exists",
                new Exception("Customer already exists: " + existingCustomer.ToStringInternal()));
        }
        var customer = customerService.CreateCustomerWithKey(loginName, firstName, lastName, email);
        var address1 = new Address
        {
            Name = addressName,
            Address1 = addressAddress1,
            Address2 = addressAddress2,
            AddressType = AddressType.Billing,
            Organization = addressOrganization,
            Locality = addressLocality,
            Region = addressRegion,
            Phone = addressPhone,
            PostalCode = addressPostalCode,
            CountryCode = addressCountryCode
        };
        var address2 = new Address
        {
            Name = addressName,
            Address1 = addressAddress1,
            Address2 = addressAddress2,
            AddressType = AddressType.Shipping,
            Organization = addressOrganization,
            Locality = addressLocality,
            Region = addressRegion,
            Phone = addressPhone,
            PostalCode = addressPostalCode,
            CountryCode = addressCountryCode
        };
        customer.CreateCustomerAddress(address1, "defaultBilling", address1.AddressType);
        customer.CreateCustomerAddress(address2, "defaultShipping", address2.AddressType);
        customerService.Save(customer);
    
        createdCustomer.Customer = customer;
        createdCustomer.CustomerCreated = true;
    
        var newMemberModelFactory = new NewMemberModelFactory<NewMemberModel>();
        Mandate.ParameterNotNull(newMemberModelFactory, "newMemberModelFactory");
        NewMemberModelFactory = newMemberModelFactory;
    
        var umbracoServices = ApplicationContext.Current.Services;
        var memberService = umbracoServices.MemberService;
    
        var model = new NewMemberModel
        {
            FirstName = firstName,
            LastName = lastName,
            Email = email,
            Password = password,
            MemberTypeAlias = "merchelloCustomer",
            ViewData = new StoreViewData(),
            PersistLogin = false
        };
    
        var registerModel = Members.CreateRegistrationModel(model.MemberTypeAlias);
        registerModel.Name = model.Email;
        registerModel.Email = model.Email;
        registerModel.Password = model.Password;
        registerModel.Username = model.Email;
        registerModel.UsernameIsEmail = true;
    
        var fn = new UmbracoProperty { Alias = "firstName", Name = "First Name", Value = model.FirstName };
        var ln = new UmbracoProperty { Alias = "lastName", Name = "Last Name", Value = model.LastName };
        registerModel.MemberProperties.Add(fn);
        registerModel.MemberProperties.Add(ln);
    
        MembershipCreateStatus status;
    
        //// Add a message for the attempt
        MultiLogHelper.Info<CreateCustomerResponse>("Registering a new member", logData);
    
        var membership = Members.RegisterMember(registerModel, out status, model.PersistLogin);
    
        var registration = NewMemberModelFactory.Create(model, status);
    
        if (registration.ViewData.Success)
        {
            var member = memberService.GetByEmail(model.Email);
    
            if (membership != null)
            {
                member.AddAjourLicenceKey(ajourLicenceKey);
                memberService.AssignRole(member.Id, "Customers");
                memberService.Save(member);
                createdCustomer.Member = member;
                createdCustomer.MemberCreated = true;
            }
    
        }
    
        Notification.Trigger("CustomerCreated", customer, new []{customer.Email}, Topic.Notifications);
    
        var response = new HttpResponseMessage
        {
            Content = new ObjectContent<CreateCustomerResponse>(createdCustomer, this.Configuration.Formatters.JsonFormatter),
            StatusCode = HttpStatusCode.Created
        };
        return response;
    }
    
    private class CreateCustomerResponse
    {
        public ICustomer Customer = null;
        public bool CustomerCreated = false;
        public IMember Member = null;
        public bool MemberCreated = false;
    }
    

    Finally, I have my email body in CustomerCreated.cshtml:

    @inherits Merchello.Web.Mvc.MerchelloHelperViewPage<AjourCms.Ajour.Models.MonitorModels.ICustomerResultNotifyModel>
    @using AjourCms
    @using Merchello.Core
    @using Merchello.Core.Models
    @using Merchello.Web
    @using AjourHelpers = AjourCms.Ajour.Helpers;
    @*
        MerchelloHelperViewPage<T> inherits from UmbracoViewPage<t> and exposes the MerchelloHelper as 'Merchello'
        Example usage:  var product = Merchello.TypedProductContent(YOURPRODUCTKEY);
    *@
    @{
    
        var customer = Model.Customer;
        var imember = Model.Member;
        var customerName = customer.FullName;
    
        var licenceKeyPropName = AjourConstants.ExtendedDataKeys.LicenceKey;
        string licenceKey = "", licenceData = "";
        if (imember.HasProperty(licenceKeyPropName))
        {
            licenceKey = (string)imember.GetValue(licenceKeyPropName);
            licenceData = AjourHelpers.DecryptLicence(licenceKey);
        }
    
    
    }
    
    <p>Welcome to Ajour store, @customerName</p>
    
    <strong>Licence: @licenceKey (@licenceData)</strong>
    
  • Cory Colt 34 posts 130 karma points
    Mar 16, 2017 @ 15:27
    Cory Colt
    0

    Claudiu,

    Thank you for explaining this. I did the same thing using a new GUID and it does indeed show up in the admin side so I can create a new notification, but it still doesn't seem to actually be sending the notification. I've spent probably over 20+ hours trying to get this to send this one notification.

    It looks like you may have gone a different direction and used the ShipmentStatusChanged, does this actually work for you when you fulfill an order and mark it as "shipped", does it send the notification? If so, would you mind explaining how you got it working?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Mar 16, 2017 @ 15:53
    Rusty Swayne
    0

    Hey Claudiu -

    You should be able to execute your trigger using the Notification helper.

       // any recipients not listed in the back office, like the website user
       var recipients = new[] {  "[email protected]" }; 
    
       Notification.Trigger("CustomerCreated", [The ICustomer object],  recipients);
    
  • Claudiu Bria 34 posts 146 karma points
    Mar 16, 2017 @ 19:52
    Claudiu Bria
    0

    Hi Cory,

    Yes, the OrderShipped notification based internally on the ShipmentServiceStatusChanged is working fine.

    Have you seen the plug for that in the UmbracoEventHandler.cs ? Take a look in the Merchello.FastTrack.UI project, there, the UmbracoEventHandler.cs file contains the following fragment:

        /// <summary>
        /// Handles Umbraco Starting.
        /// </summary>
        /// <param name="umbracoApplication">
        /// The <see cref="UmbracoApplicationBase"/>.
        /// </param>
        /// <param name="applicationContext">
        /// Umbraco <see cref="ApplicationContext"/>.
        /// </param>
        public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            // We handle the Initializing event so that we can set the parent node of the virtual content to the store
            // so that published content queries in views will work correctly
            ProductContentFactory.Initializing += ProductContentFactoryOnInitializing;
    
            MemberService.Saved += MemberServiceSaved;
    
            // ShipmentService.StatusChanged += ShipmentServiceStatusChanged;
        }
    
        ///// <summary>
        ///// Example shipment shipped / delivered notification handler
        ///// </summary>
        ///// <param name="sender">
        ///// The sender.
        ///// </param>
        ///// <param name="e">
        ///// The <see cref="StatusChangeEventArgs{IShipment}"/>
        ///// </param>
        //private void ShipmentServiceStatusChanged(IShipmentService sender, StatusChangeEventArgs<IShipment> e)
        //{
        //    var validKeys = new[] 
        //                    {
        //                        Core.Constants.DefaultKeys.ShipmentStatus.Delivered,
        //                        Core.Constants.DefaultKeys.ShipmentStatus.Shipped
        //                    };
    
        //    foreach (var shipment in e.StatusChangedEntities)
        //    {
        //        if (!validKeys.Contains(shipment.ShipmentStatus.Key)) continue;
    
        //        LogHelper.Info<UmbracoEventHandler>(string.Format("Raising notification trigger for shippment no. {0}", shipment.ShipmentNumber));
    
        //        Notification.Trigger("OrderShipped", shipment, Core.Observation.Topic.Notifications);
        //    }
        //}
    

    Similarly, in your project add an UmbracoEventHandler.cs and un-comment the line

        // ShipmentService.StatusChanged += ShipmentServiceStatusChanged;
    

    and the ShipmentServiceStatusChanged method definition below it.

  • Cory Colt 34 posts 130 karma points
    Mar 17, 2017 @ 15:38
    Cory Colt
    0

    Claudiu,

    Thank you very much for the reply! I have added a new file called UmbracoEventHandler.cs in my root directory and have copied/pasted the code you shared. The only thing I'm running into now is on these lines

    Core.Constants.DefaultKeys.ShipmentStatus.Delivered,
    Core.Constants.DefaultKeys.ShipmentStatus.Shipped
    

    It doesn't seem to know what Core is referring to. The only options I have to fix it is to make it part of the ClientDependency.Core, Merchello.Core, or Umbraco.Core, but none of them seem to work and this is preventing me from being able to compile the project.

    I do have FastTrack installed, but I had downloaded it off of the Merchello project site (https://our.umbraco.org/projects/collaboration/merchello/) and I don't see any file called UmbracoEventHandler.cs that it would have installed, so I created my own as you suggested.

    Do you know what namespace Core is referring to? in the above code snippet?

  • Claudiu Bria 34 posts 146 karma points
    Mar 17, 2017 @ 17:11
    Claudiu Bria
    1

    Hi Cory,

    On the page you mentioned you downloaded Merchello (https://our.umbraco.org/projects/collaboration/merchello/) you can find the paragraph:

    Contribute

    We would love and need your help. If you want to contribute to Merchello's core, the easiest way to get started is to fork the project on https://github.com/merchello/Merchello and open src/Merchello.sln in Visual Studio. We're excited to see what you do!

    The link inside that paragraph will take you to the source code for you to download. Use the [Branch: merchello-dev] dropdown/button to select a specific version (like 2.5.0) or leave it as is to get the currenly-in-development version (that should be somewhere between 2.5.0 and 2.6.0 as of today) and then use the [Clone or download] button on the right, then the [Download ZIP] button there.

    You will get the Visual Studio solution packed in a ZIP and if you open that you'll get inside the Merchello.FastTrack.Ui project with its own UmbracoEventHandler.cs file. It is also helpful to browse a little the whole solution and see other UmbracoEventHandler.cs files in the root of other projects.

    You can then easily get the used namespaces for different internals/publics there.

    One more little detail: the lines

                            Core.Constants.DefaultKeys.ShipmentStatus.Delivered,
                            Core.Constants.DefaultKeys.ShipmentStatus.Shipped
    

    will stumble into the .DefaultKeys on a recent Merchello namespace. Just remove them and all should be fine:

                                Core.Constants.ShipmentStatus.Delivered,
                                Core.Constants.ShipmentStatus.Shipped
    

    For your quick convenience, here below is my UmbracoEventHandler.cs. Maybe you can fix your namespace from this alone, but I still recommend you to get the source code version of Merchello/FastTrack for your development.

    using System.Linq;
    using Merchello.Core.Events;
    using Merchello.Core.Models;
    using Merchello.Core.Services;
    using Umbraco.Core;
    using Umbraco.Core.Logging;
    
    namespace AjourCms
    {
        using Notification = Merchello.Core.Notification;
    
        /// <summary>
        /// Registers Umbraco event handlers.
        /// </summary>
        public class UmbracoEventHandler : IApplicationEventHandler
        {
            /// <summary>
            /// Handles Umbraco Initialized Event.
            /// </summary>
            /// <param name="umbracoApplication">
            /// The <see cref="UmbracoApplicationBase"/>.
            /// </param>
            /// <param name="applicationContext">
            /// Umbraco <see cref="ApplicationContext"/>.
            /// </param>
            public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
            }
    
            /// <summary>
            /// Handles Umbraco Starting.
            /// </summary>
            /// <param name="umbracoApplication">
            /// The <see cref="UmbracoApplicationBase"/>.
            /// </param>
            /// <param name="applicationContext">
            /// Umbraco <see cref="ApplicationContext"/>.
            /// </param>
            public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
    //            OrderService.StatusChanged += OrderServiceStatusChanged;
                ShipmentService.StatusChanged += ShipmentServiceStatusChanged;
            }
    
            //private void OrderServiceStatusChanged(IOrderService sender, StatusChangeEventArgs<IOrder> e)
            //{
            //    var validKeys = new[]
            //                    {
            //                        Merchello.Core.Constants.OrderStatus.Fulfilled
            //                    };
    
            //    foreach (var order in e.StatusChangedEntities)
            //    {
            //        if (!validKeys.Contains(order.OrderStatus.Key)) continue;
    
            //        LogHelper.Info<UmbracoEventHandler>(string.Format("Raising notification trigger for order no. {0}", order.OrderNumber));
    
            //        Notification.Trigger("OrderConfirmation", order, Merchello.Core.Observation.Topic.Notifications);
            //    }
            //}
    
            /// <summary>
            /// Example shipment shipped / delivered notification handler
            /// </summary>
            /// <param name="sender">
            /// The sender.
            /// </param>
            /// <param name="e">
            /// The <see cref="StatusChangeEventArgs{IShipment}"/>
            /// </param>
            private void ShipmentServiceStatusChanged(IShipmentService sender, StatusChangeEventArgs<IShipment> e)
            {
                var validKeys = new[]
                                {
                                    Merchello.Core.Constants.ShipmentStatus.Delivered,
                                    Merchello.Core.Constants.ShipmentStatus.Shipped
                                };
    
                foreach (var shipment in e.StatusChangedEntities)
                {
                    if (!validKeys.Contains(shipment.ShipmentStatus.Key)) continue;
    
                    LogHelper.Info<UmbracoEventHandler>(string.Format("Raising notification trigger for shippment no. {0}", shipment.ShipmentNumber));
    
                    Notification.Trigger("OrderShipped", shipment, new []{shipment.Email}, Merchello.Core.Observation.Topic.Notifications);
                }
            }
    
            /// <summary>
            /// Handles Umbraco Started.
            /// </summary>
            /// <param name="umbracoApplication">
            /// The <see cref="UmbracoApplicationBase"/>.
            /// </param>
            /// <param name="applicationContext">
            /// Umbraco <see cref="ApplicationContext"/>.
            /// </param>
            public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
            }
    
    
        }
    }
    
Please Sign in or register to post replies

Write your reply to:

Draft