Sunday, July 22, 2012

Create Custom Scheduled Task in nopCommerce

nopCommerce is a popular open source eCommerce solution built by ASP.NET MVC framework. We can create a custom scheduled task to scan the products periodically and do some business logic there, e.g. sending out email notification if some condition reached for certain products. In order to do that we need to define a record in the ScheduleTask table. Following script inserts a scheduled task record into database that would make nopCommerce invoke 'Nop.Services.Messages.ProductScanService' every 10 minutes:
INSERT INTO ScheduleTask(Name, Seconds, [Type], [Enabled], StopOnError)
 VALUES('ProductScanService schedule', 600, 'Nop.Services.Messages.ProductScanService', 1, 0) 
The ProductScanService class implements ITask interface, and is added to nop.Services.Messages in the service layer (tested in the latest version of 2.60):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nop.Services.Tasks;
using Nop.Services.Catalog;
using Nop.Services.Logging;

namespace Nop.Services.Messages
{
    class ProductScanService : ITask
    {
        private readonly IProductService _productService;
        private readonly ILogger _logger;

        /// <summary>
        /// Dependency injection here
        /// </summary>
        public ProductScanService(IProductService productService, ILogger logger)
        {
            this._productService = productService;
            this._logger = logger;
        }

        /// <summary>
        /// Executes the task
        /// </summary>
        public void Execute()
        {
            _logger.Information(string.Format("ProductScanService starts at {0} (UTC {1})", 
                DateTime.Now, DateTime.UtcNow));
            ScanAllProducts();
            _logger.Information(string.Format("ProductScanService ends at {0} (UTC {1})",
                DateTime.Now, DateTime.UtcNow));
        }

        /// <summary>
        /// Do business logic here
        /// </summary>
        private void ScanAllProducts()
        {
            // Do stuff with _productService
        }
    }
}