Cancel order feature for customers in Nopcommerce

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
7 年 前
I have implemented the feature for customer to cancel the order. Below will help you to built similar or more advanced feature.

1.Add new property in CustomerOrderListModel.OrderDetailsModel
public bool CanCancelOrder { get; set; } 


2.Add new link in view(~/Views/Order/CustomerOrder.cshtml) so that customer can delete the order

@if (order.CanCancelOrder)
                            {
                                <input type="button" value="Cancel" class="button-2 cancel-details-button"  />
                            }


3. Now add new method in OrderProcessingService.cs and its implementation in IOrderProcessingService
public virtual bool CanCancelOrderForCustomer(Order order)
        {
            if (order == null)
                throw new ArgumentNullException("order");

            if (order.OrderStatus == OrderStatus.Cancelled || order.OrderStatus == OrderStatus.Complete)
                return false;

            //if (order.PaymentStatus == PaymentStatus.Paid)
            //    return false;
//can add more rule like customer can cancel its product only if it is with 10 days.

            return true;
        }


4. Now In OrderController.cs in PrepareCustomerOrderListModel declare your property and call the method created in OrderProcessingService
protected virtual CustomerOrderListModel PrepareCustomerOrderListModel()
        {
            var model = new CustomerOrderListModel();
            var orders = _orderService.SearchOrders(storeId: _storeContext.CurrentStore.Id,
                customerId: _workContext.CurrentCustomer.Id);
            foreach (var order in orders)
            {
                var orderModel = new CustomerOrderListModel.OrderDetailsModel
                {
                    Id = order.Id,
                    CreatedOn = _dateTimeHelper.ConvertToUserTime(order.CreatedOnUtc, DateTimeKind.Utc),
                    OrderStatusEnum = order.OrderStatus,
                    OrderStatus = order.OrderStatus.GetLocalizedEnum(_localizationService, _workContext),
                    PaymentStatus = order.PaymentStatus.GetLocalizedEnum(_localizationService, _workContext),
                    ShippingStatus = order.ShippingStatus.GetLocalizedEnum(_localizationService, _workContext),
                    IsReturnRequestAllowed = _orderProcessingService.IsReturnRequestAllowed(order),
                    CanCancelOrder = _orderProcessingService.CanCancelOrderForCustomer(order),
                    CanReturnOrder = _orderProcessingService.CanReturnOrder(order)
                };
                var orderTotalInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderTotal, order.CurrencyRate);
                orderModel.OrderTotal = _priceFormatter.FormatPrice(orderTotalInCustomerCurrency, true, order.CustomerCurrencyCode, false, _workContext.WorkingLanguage);

                model.Orders.Add(orderModel);
            }

            var recurringPayments = _orderService.SearchRecurringPayments(_storeContext.CurrentStore.Id,
                _workContext.CurrentCustomer.Id);
            foreach (var recurringPayment in recurringPayments)
            {
                var recurringPaymentModel = new CustomerOrderListModel.RecurringOrderModel
                {
                    Id = recurringPayment.Id,
                    StartDate = _dateTimeHelper.ConvertToUserTime(recurringPayment.StartDateUtc, DateTimeKind.Utc).ToString(),
                    CycleInfo = string.Format("{0} {1}", recurringPayment.CycleLength, recurringPayment.CyclePeriod.GetLocalizedEnum(_localizationService, _workContext)),
                    NextPayment = recurringPayment.NextPaymentDate.HasValue ? _dateTimeHelper.ConvertToUserTime(recurringPayment.NextPaymentDate.Value, DateTimeKind.Utc).ToString() : "",
                    TotalCycles = recurringPayment.TotalCycles,
                    CyclesRemaining = recurringPayment.CyclesRemaining,
                    InitialOrderId = recurringPayment.InitialOrder.Id,
                    CanCancel = _orderProcessingService.CanCancelRecurringPayment(_workContext.CurrentCustomer, recurringPayment),
                };

                model.RecurringOrders.Add(recurringPaymentModel);
            }

            return model;
        }


5. Write an action method for canceling any product in OrderController.cs
public ActionResult Cancel(int orderId)
        {
            var order = _orderService.GetOrderById(orderId);
            if (order == null || order.Deleted || _workContext.CurrentCustomer.Id != order.CustomerId)
                return new HttpUnauthorizedResult();

            //Add some more validation check
            if(_orderProcessingService.CanCancelOrder(order))
            {
                _orderProcessingService.CancelOrder(order, true);
            }
return RedirectToRoute("CustomerOrders");
        }


6. Register new route in RouteProvider under RegisterRoutes
routes.MapLocalizedRoute("CancelOrder",
                            "cancelorder/{orderId}",
                            new { controller = "Order", action = "Cancel" },
                            new { orderId = @"\d+" },
                            new[] { "Nop.Web.Controllers" });


7. In your view(~/Views/Order/CustomerOrder.cshtml) define the cancel button click event
@if (order.CanCancelOrder)
                            {
                                <input type="button" value="Cancel" class="button-2 cancel-details-button" onclick="setLocation('@Url.RouteUrl("CancelOrder", new { orderId = order.Id })')" />
                            }



Thats it !!!!!!

This was coded in 3.60
7 年 前
Amazing, I was desperately looking for this, thank you so much! its working on 3.80 no problems!
I want to make some suggestions:

*Steps 2 and 7 could be just one.

*on step 3 in the IOrderProcessingService.cs add the line:
bool CanCancelOrderForCustomer(Order order);


*on step 4 in the first glance its not clear where the new line is:

var orderModel = new CustomerOrderListModel.OrderDetailsModel
                {
                    Id = order.Id,
                    CreatedOn = _dateTimeHelper.ConvertToUserTime(order.CreatedOnUtc, DateTimeKind.Utc),
                    OrderStatusEnum = order.OrderStatus,
                    OrderStatus = order.OrderStatus.GetLocalizedEnum(_localizationService, _workContext),
                    PaymentStatus = order.PaymentStatus.GetLocalizedEnum(_localizationService, _workContext),
                    ShippingStatus = order.ShippingStatus.GetLocalizedEnum(_localizationService, _workContext),
                    IsReturnRequestAllowed = _orderProcessingService.IsReturnRequestAllowed(order),
                    CanCancelOrder = _orderProcessingService.CanCancelOrderForCustomer(order) //new
                };


*On step 4 you dont need this line of code:
CanReturnOrder = _orderProcessingService.CanReturnOrder(order)


*You may add the path for some files:
- on step 1: \Presentation\Nop.Web\Models\Order\CustomerOrderListModel.cs
- on step 3: \Libraries\Nop.Services\Orders
- on step 4: \Presentation\Nop.Web\Controllers
- on step 5: \Presentation\Nop.Web\Controllers
- on step 6: \Presentation\Nop.Web\Infrastructure\RouteProvider.cs
5 年 前
Excellent work...

Just for your information, I have done this in version 3.9 with minor modification
in step 4

OrderModelFactory.cs
var orderModel = new CustomerOrderListModel.OrderDetailsModel
{
    Id = order.Id,
    CreatedOn = _dateTimeHelper.ConvertToUserTime(order.CreatedOnUtc, DateTimeKind.Utc),
    OrderStatusEnum = order.OrderStatus,
    OrderStatus = order.OrderStatus.GetLocalizedEnum(_localizationService, _workContext),
    PaymentStatus = order.PaymentStatus.GetLocalizedEnum(_localizationService, _workContext),
    ShippingStatus = order.ShippingStatus.GetLocalizedEnum(_localizationService, _workContext),
    IsReturnRequestAllowed = _orderProcessingService.IsReturnRequestAllowed(order),
    CustomOrderNumber = order.CustomOrderNumber,
    CanCancelOrder = _orderProcessingService.CanCancelOrderForCustomer(order)
};
3 年 前
Hi,
Does the code still work for version 4.2 and 4.4?
i need to provide modify order feature i.e. cancel the order and copy the order items into the shopping cart.
thanks.
3 年 前
Just found that version 4.2 contains CanCancelOrder and CancelOrder methods in OrderProcessingService, although CancelOrder will need some customization depending on each store's behavior.
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.