public ActionResult SaleProductAddPopup(int saleId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts))
                return View("~/Administration/Views/Security/AccessDenied.cshtml");

            var model = new AULotList();  //using same search model as ManageLots

            //a vendor should have access only to his products. Set the indicator in the model
            model.IsLoggedInAsVendor = _workContext.CurrentVendor != null;
            model.SaleId = saleId;

            //categories
            model.AvailableCategories.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            var categories = _categoryService.GetAllCategories(showHidden: true);
            foreach (var c in categories)
                model.AvailableCategories.Add(new SelectListItem { Text = c.GetFormattedBreadCrumb(categories), Value = c.Id.ToString() });

            //NJM: Sales
            model.AvailableSales.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            var sales = _consignorService.GetAllSales(
                 saleId: saleId,
                 saleNbr: null,
                 saleTitle: null,
                 excludeSale: true,
                 pageIndex: 0,
                 pageSize: 2147483647);
            foreach (var c in sales)
                model.AvailableSales.Add(new SelectListItem { Text = c.AUSaleNbr, Value = c.AUSaleID.ToString() });

            //stores
            model.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var s in _storeService.GetAllStores())
                model.AvailableStores.Add(new SelectListItem { Text = s.Name, Value = s.Id.ToString() });

            //warehouses
            model.AvailableWarehouses.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var wh in _shippingService.GetAllWarehouses())
                model.AvailableWarehouses.Add(new SelectListItem { Text = wh.Name, Value = wh.Id.ToString() });

            //product types
            //NJM: Note ToSelectList is an extension method in Nop.Web.Framework
            model.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList();
            model.AvailableProductTypes.Insert(0, new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });


            //"published" property
            //0 - all (according to "ShowHidden" parameter)
            //1 - published only
            //2 - unpublished only
            model.AvailablePublishedOptions.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Catalog.Products.List.SearchPublished.All"), Value = "0" });
            model.AvailablePublishedOptions.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Catalog.Products.List.SearchPublished.PublishedOnly"), Value = "1" });
            model.AvailablePublishedOptions.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Catalog.Products.List.SearchPublished.UnpublishedOnly"), Value = "2" });

            return View("~/Views/AUConsignor/ManageSaleLotsPopup.cshtml", model);
        }
        public ActionResult SaleProductAddPopup(string selectedIds, int saleId, string btnIdToRefresh, string frmIdToRefresh, AULotList model)
        {
            //TODO: Implement permissions
            //if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts))
            //    return AccessDeniedView();

            
            var sale = _consignorService.GetSaleById(saleId);
            if (sale == null)
            {
                ErrorNotification("A major error occurred -sale id from SaleProductAddPopup not found. Please contact System Support");
                return RedirectToAction("ManageSales"); 
            }
            
            //TODO: Finish this - Need to get the lot info to ensure not already sold and unpublished
            var lots = new List<AULotRecord>();
            if (selectedIds != null)
            {
                lots.AddRange(_consignorService.GetLotsByPids(selectedIds));
            }


            //sale = new sale
            //l = lot

            //

            int totalerrors = 0;
            string logError = "";
            DateTime currTime = DateTime.UtcNow;
            foreach (var l in lots)
            {
                var newSaleLot = new AUSaleLotRecord
                {
                    AUSaleID = sale.AUSaleID,
                    AULotID = l.AULotID,
                    AUProductId = l.AUProductID,
                    Sku = l.Sku,
                    LotNbr = 0,
                    SaleIsActive = sale.SaleIsActive,       //pull this indicator from the Sale record - don't load from spreadsheet
                    DisplayOrder = 0,
                    SaleStartDateTime = sale.SaleStartDateTime,
                    SaleEndDateTime = sale.SaleEndDateTime
                };

                var CurrentCustomer = _authenticationService.GetAuthenticatedCustomer();
                //var oldSaleLot = l.AUSaleRecords.FirstOrDefault(); //&&&&&& get the sale this lot associated to that is not history and not = current sale
                var oldSaleLot = l.AUSaleRecords.FirstOrDefault(x => !x.IsHistory);

                if (oldSaleLot != null)
                {
                    if (oldSaleLot.AUSaleID != sale.AUSaleID)  //you're moving lot from one sale to another
                    {
                        //lot 1) can't be sold or 2) be in an active or future sale and have bids
                        //note: it CAN be unpublished and it CAN be deleted, though the front-end selection will filter these
                        if (l.IsLotSold ||
                            (!l.IsLotSold && oldSaleLot.SaleStartDateTime  < currTime &&  oldSaleLot.SaleEndDateTime  > currTime && l.LastBidDateTime != null) ||
                            (!l.IsLotSold && oldSaleLot.SaleStartDateTime > currTime && oldSaleLot.SaleEndDateTime > currTime && l.LastBidDateTime != null)
                            )
                        {
                            logError = string.Format("Move Lot to Sale by user {2} : Ignoring this lot id# {0}/ Sku# {1} is sold or is in an active or future sale and has had bids", l.AULotID, l.Sku, CurrentCustomer.Username);
                            _logger.InsertLog(LogLevel.Error, logError);
                            totalerrors++;
                        }
                        else
                        {
                            //move lot from to new sale and record lot history for MOVE (MV)
                            _consignorService.MoveSaleLot(oldSaleLot, newSaleLot);

                        }
                    }
                    //Note: no action because already in that sale but log warning anyway
                    logError = string.Format("Move Lot to Sale by user {2} : This lot id# {0}/ Sku# {1} was not moved because it is already in sale id {3}", l.AULotID, l.Sku, CurrentCustomer.Username, sale.AUSaleID);
                    _logger.InsertLog(LogLevel.Error, logError);
                    totalerrors++;
                }
                else
                //this lot was not currenty associated to any sale so just associate it and record lot history (NS)
                {
                    _consignorService.InsertSaleLot(newSaleLot);
                }

            }


            ////a vendor should have access only to his products
            //if (_workContext.CurrentVendor != null)
            //{
            //    products = products.Where(p => p.VendorId == _workContext.CurrentVendor.Id).ToList();
            //}


            //_consignorService.PublishSelectedProducts(products);


            SuccessNotification("Lots were associated to sale!!");  //seems to be nop admin convention

            ViewBag.RefreshPage = true;
            ViewBag.btnId = btnIdToRefresh;
            ViewBag.formId = frmIdToRefresh;
            return View("~/Views/AUConsignor/ManageSaleLotsPopup.cshtml", model);
            //return RedirectToAction("ListLots"); //TODO FIX THIS
        }
        public ActionResult ListSaleLots(DataSourceRequest command, AULotList model, int excludeSaleId, bool excludeSale, AUSoldUnsoldEnum soldUnsold )
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts))
                return View("~/Administration/Views/Security/AccessDenied.cshtml");

            
            //0 - all (according to "ShowHidden" parameter)
            //1 - published only
            //2 - unpublished only
            //bool? overridePublished = false; //show published and unpublished lots associated to the sale the sale

            //should not happen
            if (model.SearchSaleId == 0 && excludeSaleId != 0 && excludeSale == false )
            {
                model.SearchSaleId = excludeSaleId;
            }


            //NOTE: 2 entry points will either 
            // 1) want to see unsold lots not in the current sale (add sale to lot popup) or 
            // 2) want to see all (sold/unsold) lots in this sale (sale-lots display)
            var lots = _consignorService.GetAllLots(
                saleId: model.SearchSaleId,
                pageIndex: command.Page - 1,
                pageSize: command.PageSize,
                overridePublished: true,                            //only show published
                showHidden: false,                                  //only show non-deleted
                excludeSale: excludeSale,
                excludeSaleId: excludeSaleId,
                soldUnsold: soldUnsold                 ///only show unsolds from other sales or in no sale to move into this sale
            );

             //overridePublished: overridePublished,


            //var lots = _consignorService.GetAllLots(
            //    categoryIds: categoryIds,
            //    saleId: model.SearchSaleId,
            //    storeId: model.SearchStoreId,
            //    warehouseId: model.SearchWarehouseId,
            //    productType: model.SearchProductTypeId > 0 ? (AUProductType?)model.SearchProductTypeId : null,
            //    keywords: model.SearchProductName,
            //    pageIndex: command.Page - 1,
            //    pageSize: command.PageSize,
            //    showHidden: true,
            //    overridePublished: overridePublished
            //);


            var gridModel = new DataSourceResult();
            gridModel.Data = lots.Select(x =>
            {
                var lotsModel = x.ToModel();  //ToModel uses EF mapper and is implemented as an Extension. Map definition is in Infrastructure\AutomapperStartupTask
                lotsModel.Id = x.Id;
                lotsModel.ProductID = x.ProductID;
                lotsModel.AULotID = x.AULotID;
                lotsModel.Name = x.Name;
                lotsModel.ShortDescription = x.ShortDescription;
                lotsModel.SKU = x.SKU;
                lotsModel.LotNbr = x.LotNbr;
                lotsModel.IsLotSold = x.IsLotSold;
                lotsModel.AUSaleID = x.AUSaleID;
                lotsModel.AUSaleNbr = x.AUSaleNbr;
                lotsModel.SaleTitle = x.SaleTitle;
                lotsModel.Published = x.Published;

                //little hack here:
                //ensure that product full descriptions are not returned
                //otherwise, we can get the following error if products have too long descriptions:
                //"Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property. "
                //also it improves performance
                //-->productModel.FullDescription = "";

                //picture
                var defaultProductPicture = _pictureService.GetPicturesByProductId(x.ProductID, 1).FirstOrDefault();

                lotsModel.PictureThumbnailUrl = _pictureService.GetPictureUrl(defaultProductPicture, 75, true);

                //product type
                //productModel.ProductTypeName = x.ProductType.GetLocalizedEnum(_localizationService, _workContext);

                //friendly stock qantity
                //if a simple product AND "manage inventory" is "Track inventory", then display
                //if (x.ProductType == ProductType.SimpleProduct && x.ManageInventoryMethod == ManageInventoryMethod.ManageStock)
                //    productModel.StockQuantityStr = x.GetTotalStockQuantity().ToString();

                return lotsModel;
            });
            gridModel.Total = lots.TotalCount;

            return Json(gridModel);
        }
        public ActionResult LotList(DataSourceRequest command, AULotList model)
        {

            if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts))
                return View("~/Administration/Views/Security/AccessDenied.cshtml");

            //TODO: add in vendor logic for consignors to see their lots. See C:\Users\Nicholas\Documents\My Documents\NopCommerce\Presentation\Nop.Web\Administration\Controllers\ProductController.cs ProductList()


            var categoryIds = new List<int> { model.SearchCategoryId };
            //include subcategories
            if (model.SearchIncludeSubCategories && model.SearchCategoryId > 0)
                categoryIds.AddRange(GetChildCategoryIds(model.SearchCategoryId));


            //0 - all (according to "ShowHidden" parameter)
            //1 - published only
            //2 - unpublished only
            bool? overridePublished = null;
            if (model.SearchPublishedId == 1)
                overridePublished = true;
            else if (model.SearchPublishedId == 2)
                overridePublished = false;


            //this will not conside exclude sale, as it general use for Manage Lots
            var lots = _consignorService.GetAllLots(
                categoryIds: categoryIds,
                saleId: model.SearchSaleId,
                storeId: model.SearchStoreId,
                warehouseId: model.SearchWarehouseId,
                productType: model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null,
                keywords: model.SearchProductName,
                pageIndex: command.Page - 1,
                pageSize: command.PageSize,
                showHidden: true,
                overridePublished: overridePublished
            );


            //int productid = 0;
            //string firstname = "Test";
            //string lastname = "";

            //int productId = model.searchProductID;
            //string searchname = model.searchName;
            //%%%%%%%%%%%start cleaning here
            //var lots = _consignorService.GetAllLots(
            //    //productId: productId,
            //    //searchname: searchname,
            //    pageIndex: 0,
            //    pageSize: 500);

            //pageIndex: command.Page - 1,
            //pageSize: command.PageSize);
            



 
            //TODO: THIS WILL NEED TO BE CHANGED WHEN YOU IMPLEMENT MORE THAN ONE CONSIGNOR PER CONSIGNMENT
            //%%%%%%%%%%lots is food - something wrong with the view
            //var gridModel = new DataSourceResult
            //{
            //    Data = lots.Select(x => new
            //    {

            //        Id = x.Id,
            //        ProductID = x.ProductID,
            //        Name = x.Name,
            //        ShortDescription = x.ShortDescription,
            //        LotNbr = x.LotNbr,
            //        AUSaleID = x.AUSaleID,
            //        AUSaleNbr = x.AUSaleNbr,
            //        SaleTitle = x.SaleTitle

            //    }),
            //    Total = lots.TotalCount
            //};


            var gridModel = new DataSourceResult();
            gridModel.Data = lots.Select(x =>
            {
                var lotsModel = x.ToModel();  //ToModel uses EF mapper and is implemented as an Extension. Map definition is in Infrastructure\AutomapperStartupTask
                lotsModel.Id = x.Id;
                lotsModel.ProductID = x.ProductID;
                lotsModel.AULotID = x.AULotID;
                lotsModel.Name = x.Name;
                lotsModel.ShortDescription = x.ShortDescription;
                lotsModel.SKU = x.SKU;
                lotsModel.LotNbr = x.LotNbr;
                lotsModel.IsLotSold = x.IsLotSold;
                lotsModel.AUSaleID = x.AUSaleID;
                lotsModel.SaleIsActive = x.SaleIsActive;
                lotsModel.AUSaleNbr = x.AUSaleNbr;
                lotsModel.SaleTitle = x.SaleTitle;
                lotsModel.Published = x.Published;
               
                //little hack here:
                //ensure that product full descriptions are not returned
                //otherwise, we can get the following error if products have too long descriptions:
                //"Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property. "
                //also it improves performance
                //-->productModel.FullDescription = "";

                

                //picture
                var defaultProductPicture = _pictureService.GetPicturesByProductId(x.ProductID, 1).FirstOrDefault();

                lotsModel.PictureThumbnailUrl = _pictureService.GetPictureUrl(defaultProductPicture, 75, true);
                
                //product type
                //productModel.ProductTypeName = x.ProductType.GetLocalizedEnum(_localizationService, _workContext);
                
                //friendly stock qantity
                //if a simple product AND "manage inventory" is "Track inventory", then display
                //if (x.ProductType == ProductType.SimpleProduct && x.ManageInventoryMethod == ManageInventoryMethod.ManageStock)
                //    productModel.StockQuantityStr = x.GetTotalStockQuantity().ToString();
               
                return lotsModel;
            });
            gridModel.Total = lots.TotalCount;



            return Json(gridModel);

        }
        public ActionResult DownloadCatalogAsPdf(AULotList model)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts))
                return View("~/Administration/Views/Security/AccessDenied.cshtml");
                //return AccessDeniedView();

            ////a vendor should have access only to his products
            //if (_workContext.CurrentVendor != null)
            //{
            //    model.SearchVendorId = _workContext.CurrentVendor.Id;
            //}

            var categoryIds = new List<int> { model.SearchCategoryId };
            //include subcategories
            if (model.SearchIncludeSubCategories && model.SearchCategoryId > 0)
                categoryIds.AddRange(GetChildCategoryIds(model.SearchCategoryId));


            //0 - all (according to "ShowHidden" parameter)
            //1 - published only
            //2 - unpublished only
            bool? overridePublished = null;
            if (model.SearchPublishedId == 1)
                overridePublished = true;
            else if (model.SearchPublishedId == 2)
                overridePublished = false;


            //this will not conside exclude sale, as it general use for Manage Lots
            var products = _consignorService.GetAllLots(
                categoryIds: categoryIds,
                saleId: model.SearchSaleId,
                storeId: model.SearchStoreId,
                warehouseId: model.SearchWarehouseId,
                productType: model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null,
                keywords: model.SearchProductName,
                //pageIndex: command.Page - 1,
                //pageSize: command.PageSize,
                showHidden: true,
                overridePublished: overridePublished
            );

            try
            {
                byte[] bytes;
                using (var stream = new MemoryStream())
                {
                    _philatelicpdfService.PrintProductsToPdf(stream, products);
                    bytes = stream.ToArray();
                }
                return File(bytes, "application/pdf", "pdfcatalog.pdf");
            }
            catch (Exception exc)
            {
                ErrorNotification(exc);
                return RedirectToAction("ListLots");
            }
        }
        public ActionResult ExportExcelAll(AULotList model)
        {
            //throw new NotImplementedException("exportexcel-all button not implemented yet"); //need way to edit lot

            //if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts))
            //    return AccessDeniedView();

            ////a vendor should have access only to his products
            //if (_workContext.CurrentVendor != null)
            //{
            //    model.SearchVendorId = _workContext.CurrentVendor.Id;
            //}

            var categoryIds = new List<int> { model.SearchCategoryId };
            //include subcategories
            if (model.SearchIncludeSubCategories && model.SearchCategoryId > 0)
                categoryIds.AddRange(GetChildCategoryIds(model.SearchCategoryId));

            //0 - all (according to "ShowHidden" parameter)
            //1 - published only
            //2 - unpublished only
            bool? overridePublished = null;
            if (model.SearchPublishedId == 1)
                overridePublished = true;
            else if (model.SearchPublishedId == 2)
                overridePublished = false;

            //var products = _productService.SearchProducts(
            //    categoryIds: categoryIds,
            //    manufacturerId: model.SearchManufacturerId,
            //    storeId: model.SearchStoreId,
            //    vendorId: model.SearchVendorId,
            //    warehouseId: model.SearchWarehouseId,
            //    productType: model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null,
            //    keywords: model.SearchProductName,
            //    showHidden: true,
            //    overridePublished: overridePublished
            //);


            var products = _consignorService.GetAllLots(
               categoryIds: categoryIds,
               saleId: model.SearchSaleId,
               storeId: model.SearchStoreId,
               warehouseId: model.SearchWarehouseId,
               productType: model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null,
               keywords: model.SearchProductName,
                //pageIndex: command.Page - 1,
                //pageSize: command.PageSize,
               showHidden: true,
               overridePublished: overridePublished
           );



            try
            {
                byte[] bytes;
                using (var stream = new MemoryStream())
                {
                    //_exportManager.ExportProductsToXlsx(stream, products);
                    _collectibleexportService.ExportPhilatelicProductsToXlsx(stream, products);
                    bytes = stream.ToArray();
                }
                return File(bytes, "text/xls", "products.xlsx");
            }
            catch (Exception exc)
            {
                ErrorNotification(exc);
                return RedirectToAction("ListLots");
            }
        }
 public ActionResult GoToSku(AULotList model)   
 {
     throw new NotImplementedException(); //need way to edit lot
     //Console.Write("hit the button");
     //return new NullJsonResult();
 }