Adding new functionalities to nopCommerce. Is this the right way?

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
4 years ago
Hi guys, I have been looking at nopCommerce code for just a couple of weeks and I wanted to add a page in the admin area that would show me a summary of orders grouped by Status. In my particular application I need to have much more statuses for an order that the four defined in the enum so the only core code that I touched is Libraries\Nop.Core\Domain\Orders\OrderStatus.cs which contain an enumerator. So I added several new values.

Let's start from the final goal. This is what I needed:



So as you can see from the picture I achieved my goal. My question is did I do it in the correct way?

1) I added few more status to the enum OrderStatus:

namespace Nop.Core.Domain.Orders
{
    /// <summary>
    /// Represents an order status enumeration
    /// </summary>
    public enum OrderStatus
    {
        /// <summary>
        /// Pending
        /// </summary>
        Pending = 10,

        /// <summary>
        /// Processing
        /// </summary>
        Processing = 20,

        /// <summary>
        /// Complete
        /// </summary>
        Complete = 30,

        /// <summary>
        /// Cancelled
        /// </summary>
        Cancelled = 40,

        InStoreToPrint = 50,
        InFullfillment = 51,
        InDesignToPrint = 52,
        InDesign = 53,
        PMToPrint = 54,
        PMToProcess = 55,
        PMComplete = 56,
        PMRssDone = 57,
        UrgentToPrint = 58,
        UrgentPrinted = 59,
        CalendarsToPrint = 60,
        CalendarsPrinted = 61,
        InProduction = 62,
        SEOToPrint = 63,
        SwordToProcess = 64,
        DropShipToProcess = 65,
        Shipped = 100
    }
}



2) I created my Model

using System;
using Nop.Core.Domain.Orders;
using Nop.Web.Framework.Models;

namespace Nop.Web.Areas.Admin.Models.Orders
{
    public class SimpleGroupedOrderModel : BaseNopEntityModel
    {
        public OrderStatus OrderStatus;
        public int HowMany;
    }
}



3) I defined a new method in Presentation\Nop.Web\Areas\Admin\Factories\IOrderModelFactory.cs

List<SimpleGroupedOrderModel> PrepareSimpleGroupedOrderModels();



4) I implemented the method PrepareSimpleGroupedOrderModels adding it to Presentation\Nop.Web\Areas\Admin\Factories\OrderModelFactory.cs

        public virtual List<SimpleGroupedOrderModel> PrepareSimpleGroupedOrderModels()
        {
            var model = new List<SimpleGroupedOrderModel>();

            var orders = from order
                         in _orderService.SearchOrders(pageSize: int.MaxValue)
                         orderby order.OrderStatus
                         group order by order.OrderStatus into g
                         select new
                         {
                             OrderStatus = g.Key,
                             HowMany = (from order in g select order.OrderStatus).Count()
                         };
            foreach (var order in orders)
            {
                model.Add(new SimpleGroupedOrderModel
                {
                    OrderStatus = order.OrderStatus,
                    HowMany = order.HowMany
                });
            }
            return model;
        }


5) I added an action in Presentation\Nop.Web\Areas\Admin\Controllers\OrderController.cs

        public virtual IActionResult Summary()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageOrders))
                return AccessDeniedView();

            var model = _orderModelFactory.PrepareSimpleGroupedOrderModels();
            return View(model);
        }



6) I created my View page

@model List<SimpleGroupedOrderModel>

@{
    //page title
    ViewBag.Title = T("Admin.Orders").Text;
    //active menu item (system name)
    Html.SetActiveMenuItemSystemName("Orders.Summary");
}

<div class="content-header clearfix">
    <h1 class="pull-left">
        @T("Admin.Orders") Summary
    </h1>
</div>
<div class="content">
    <div class="form-horizontal">
        <div class="panel-group">
            <div class="panel panel-default">
                <div class="panel-body">
                    <table class="table table-bordered table-hover table-striped dataTable"  width="100%" role="grid" style="margin-left: 0px; width: 400px;">
                        <thead>
                        <tr>
                            <th>Status</th>
                            <th>Total</th>
                        </tr>
                        </thead>
                        <tbody>
                            @foreach (var item in Model)
                            {
                                <tr>
                                    <td>@T("enums.nop.core.domain.orders.orderstatus."+item.OrderStatus.ToString()).Value</td>
                                    <td>@item.HowMany</td>
                                </tr>
                            }
                         </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>


7) I added an entry in sitemap.config

I this the correct method to add functionalities to nopCommerce or am I doing something/everything wrong?

Thank you.
4 years ago
Looks good. You can continue with this.
4 years ago
Hi Jaber, thank you for your help, I appreciate it very much. My main concern is that making changes to existing pages could make it very hard for future upgrade to newer versions of nopCommerce. There is no way to add additional methods to OrderFactory keeping them in a separate file? Same thing for IOrderFactory, there is a way to add more methods definition keeping them in a separate file? Hope this make sense. Thanks again.
4 years ago
ZenZero wrote:
Hi Jaber, thank you for your help, I appreciate it very much. My main concern is that making changes to existing pages could make it very hard for future upgrade to newer versions of nopCommerce. There is no way to add additional methods to OrderFactory keeping them in a separate file? Same thing for IOrderFactory, there is a way to add more methods definition keeping them in a separate file? Hope this make sense. Thanks again.


All service and factory classes and interfaces are partial. So you can add another partial class or interface of same type in a different file. So that you can identify extended methods in future when you want to upgrade. For example, you can add a method in OrderModelFactory this way,

Create a separate folder name Factories.Ext in Admin area

Create a class named OrderModelFactory in it. Code will be as below.
namespace Nop.Web.Areas.Admin.Factories //namespace must be same for both partial classes
{
    public partial class OrderModelFactory //no need to inherit interface here
    {

        public MyCustomModel PrepareMyCustomModel()
        {

        }

    }
}
4 years ago
GREAT! thank you very much
4 years ago
When adding new status enums, you do need to be careful that you've not affected the workflow/features.  For example, if your new statuses will be used rather than OrderStatus.Pending, then features in code looking for OrderStatus.Pending would not work correctly.  In your case, it may not be a concern, but you should check.

If "main concern is that making changes to existing pages could make it very hard for future upgrade to newer versions of nopCommerce", then consider creating a plugin.  But in that case, you would have a separate table to maintain your status.  (And you can handle events to update it.)
4 years ago
New York wrote:
When adding new status enums, you do need to be careful that you've not affected the workflow/features.  For example, if your new statuses will be used rather than OrderStatus.Pending, then features in code looking for OrderStatus.Pending would not work correctly.  In your case, it may not be a concern, but you should check.

If "main concern is that making changes to existing pages could make it very hard for future upgrade to newer versions of nopCommerce", then consider creating a plugin.  But in that case, you would have a separate table to maintain your status.  (And you can handle events to update it.)


Thank you for your advises. I appreciate it.
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.