Amend to ProductLoadAllPaged

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
12 years ago
Hi All,

I need to amend the SP 'ProductLoadAllPaged' so i can pass in a list of categories rather than 1 category.

I am using the following amended code to get all child categories for a given category and checking:

if (categoryId > 0 && categoriesIds != null && categoriesIds.Count > 0)
                    {
                        query = from p in query
                                from pc in p.ProductCategories.Where(pc => categoriesIds.Contains(pc.CategoryId))
                                where (!featuredProducts.HasValue || featuredProducts.Value == pc.IsFeaturedProduct)
                                select p;
                    }
                    else
                    {
                        query = from p in query
                                from pc in p.ProductCategories.Where(pc => pc.CategoryId == categoryId)
                                where (!featuredProducts.HasValue || featuredProducts.Value == pc.IsFeaturedProduct)
                                select p;
                    }


But I somehow need to add this into the SP so the speed remains quick!

I.e replace:

new SqlParameter { ParameterName = "CategoryId", Value = categoryId, SqlDbType = SqlDbType.Int }


With something like:

new SqlParameter { ParameterName = "CategoryIds", Value = categoriesIds, SqlDbType = SqlDbType.NVarChar}


I presume it needs to work like the FilteredSpecs id's that are passed in?

Any ideas? I'm not too good with SQL!

Many thanks,

Dave
12 years ago
Modified it, here's my code:

SQL:


USE [dbname]
GO
/****** Object:  StoredProcedure [dbo].[ProductLoadAllPaged]    Script Date: 01/25/2012 11:25:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ProductLoadAllPaged]
(
  @CategoryIds    nvarchar(300) = null,
  @ManufacturerId    int = 0,
  @ProductTagId    int = 0,
  @FeaturedProducts  bit = null,  --0 featured only , 1 not featured only, null - load all products
  @PriceMin      decimal(18, 4) = null,
  @PriceMax      decimal(18, 4) = null,
  @Keywords      nvarchar(MAX) = null,
  @SearchDescriptions bit = 0,
  @FilteredSpecs    nvarchar(300) = null,  --filter by attributes (comma-separated list). e.g. 14,15,16
  @LanguageId      int = 0,
  @OrderBy      int = 0, --0 position, 5 - Name, 10 - Price, 15 - creation date
  @PageIndex      int = 0,
  @PageSize      int = 2147483644,
  @ShowHidden      bit = 0,
  @TotalRecords    int = null OUTPUT
)
AS
BEGIN
  
  --init
  DECLARE @SearchKeywords bit
  SET @SearchKeywords = 1
  IF (@Keywords IS NULL OR @Keywords = N'')
    SET @SearchKeywords = 0

  SET @Keywords = isnull(@Keywords, '')
  SET @Keywords = '%' + rtrim(ltrim(@Keywords)) + '%'

  --filter by attributes
  SET @FilteredSpecs = isnull(@FilteredSpecs, '')
  CREATE TABLE #FilteredSpecs
  (
    SpecificationAttributeOptionId int not null
  )
  INSERT INTO #FilteredSpecs (SpecificationAttributeOptionId)
  SELECT CAST(data as int) FROM dbo.[nop_splitstring_to_table](@FilteredSpecs, ',');
  
  DECLARE @SpecAttributesCount int  
  SELECT @SpecAttributesCount = COUNT(1) FROM #FilteredSpecs
  
  --categories
  SET @CategoryIds = isnull(@CategoryIds, '')
  CREATE TABLE #CategoryIds
  (
    CategoryId int not null
  )
  INSERT INTO #CategoryIds(CategoryId)
  SELECT CAST(data as int) FROM dbo.[nop_splitstring_to_table](@CategoryIds, ',');
  
  DECLARE @CategoryCount int  
  SELECT @CategoryCount = COUNT(1) FROM #CategoryIds

  --paging
  DECLARE @PageLowerBound int
  DECLARE @PageUpperBound int
  DECLARE @RowsToReturn int
  
  SET @RowsToReturn = @PageSize * (@PageIndex + 1)  
  SET @PageLowerBound = @PageSize * @PageIndex
  SET @PageUpperBound = @PageLowerBound + @PageSize + 1
  
  CREATE TABLE #DisplayOrderTmp
  (
    [Id] int IDENTITY (1, 1) NOT NULL,
    [ProductId] int NOT NULL
  )

  INSERT INTO #DisplayOrderTmp ([ProductId])
  SELECT p.Id
  FROM Product p with (NOLOCK)
  LEFT OUTER JOIN Product_Category_Mapping pcm with (NOLOCK) ON p.Id=pcm.ProductId
  LEFT OUTER JOIN Product_Manufacturer_Mapping pmm with (NOLOCK) ON p.Id=pmm.ProductId
  LEFT OUTER JOIN Product_ProductTag_Mapping pptm with (NOLOCK) ON p.Id=pptm.Product_Id
  LEFT OUTER JOIN ProductVariant pv with (NOLOCK) ON p.Id = pv.ProductId
  --searching of the localized values
  --comment the line below if you don't use it. It'll improve the performance
  LEFT OUTER JOIN LocalizedProperty lp with (NOLOCK) ON p.Id = lp.EntityId AND lp.LanguageId = @LanguageId AND lp.LocaleKeyGroup = N'Product'
  WHERE
    (
       (
        --@CategoryId IS NULL OR @CategoryId=0
        --OR (pcm.CategoryId=@CategoryId AND (@FeaturedProducts IS NULL OR pcm.IsFeaturedProduct=@FeaturedProducts))
        
        --filter by specs
        @CategoryCount = 0
        OR
        (
          EXISTS(
            SELECT 1
            FROM #CategoryIds [cs]
            WHERE [cs].CategoryId IN (
              SELECT psam.CategoryId
              FROM dbo.Product_Category_Mapping psam
              WHERE psam.ProductId = p.Id
              )
            )
          
        )
        
      )
    AND (
        @ManufacturerId IS NULL OR @ManufacturerId=0
        OR (pmm.ManufacturerId=@ManufacturerId AND (@FeaturedProducts IS NULL OR pmm.IsFeaturedProduct=@FeaturedProducts))
      )
    AND (
        @ProductTagId IS NULL OR @ProductTagId=0
        OR pptm.ProductTag_Id=@ProductTagId
      )
    AND  (
        @ShowHidden = 1 OR p.Published = 1
      )
    AND
      (
        p.Deleted=0
      )
    AND
      (
        @ShowHidden = 1 OR pv.Published = 1
      )
    AND
      (
        @ShowHidden = 1 OR pv.Deleted = 0
      )
    AND (
        --min price
        (@PriceMin IS NULL OR @PriceMin=0)
        OR
        (
          --special price (specified price and valid date range)
          (pv.SpecialPrice IS NOT NULL AND (getutcdate() BETWEEN isnull(pv.SpecialPriceStartDateTimeUtc, '1/1/1900') AND isnull(pv.SpecialPriceEndDateTimeUtc, '1/1/2999')))
          AND
          (pv.SpecialPrice >= @PriceMin)
        )
        OR
        (
          --regular price (price isn't specified or date range isn't valid)
          (pv.SpecialPrice IS NULL OR (getutcdate() NOT BETWEEN isnull(pv.SpecialPriceStartDateTimeUtc, '1/1/1900') AND isnull(pv.SpecialPriceEndDateTimeUtc, '1/1/2999')))
          AND
          (pv.Price >= @PriceMin)
        )
      )
    AND (
        --max price
        (@PriceMax IS NULL OR @PriceMax=2147483644) -- max value
        OR
        (
          --special price (specified price and valid date range)
          (pv.SpecialPrice IS NOT NULL AND (getutcdate() BETWEEN isnull(pv.SpecialPriceStartDateTimeUtc, '1/1/1900') AND isnull(pv.SpecialPriceEndDateTimeUtc, '1/1/2999')))
          AND
          (pv.SpecialPrice <= @PriceMax)
        )
        OR
        (
          --regular price (price isn't specified or date range isn't valid)
          (pv.SpecialPrice IS NULL OR (getutcdate() NOT BETWEEN isnull(pv.SpecialPriceStartDateTimeUtc, '1/1/1900') AND isnull(pv.SpecialPriceEndDateTimeUtc, '1/1/2999')))
          AND
          (pv.Price <= @PriceMax)
        )
      )
    AND  (
        @SearchKeywords = 0 or
        (
          -- search standard content
          patindex(@Keywords, p.name) > 0
          or patindex(@Keywords, pv.name) > 0
          or patindex(@Keywords, pv.sku) > 0
          or (@SearchDescriptions = 1 and patindex(@Keywords, p.ShortDescription) > 0)
          or (@SearchDescriptions = 1 and patindex(@Keywords, p.FullDescription) > 0)
          or (@SearchDescriptions = 1 and patindex(@Keywords, pv.Description) > 0)          
          --searching of the localized values
          --comment the lines below if you don't use it. It'll improve the performance
          or (lp.LocaleKey = N'Name' and patindex(@Keywords, lp.LocaleValue) > 0)
          or (@SearchDescriptions = 1 and lp.LocaleKey = N'ShortDescription' and patindex(@Keywords, lp.LocaleValue) > 0)
          or (@SearchDescriptions = 1 and lp.LocaleKey = N'FullDescription' and patindex(@Keywords, lp.LocaleValue) > 0)
        )
      )
    AND
      (
        @ShowHidden = 1
        OR
        (getutcdate() between isnull(pv.AvailableStartDateTimeUtc, '1/1/1900') and isnull(pv.AvailableEndDateTimeUtc, '1/1/2999'))
      )
    AND
      (
        --filter by specs
        @SpecAttributesCount = 0
        OR
        (
          NOT EXISTS(
            SELECT 1
            FROM #FilteredSpecs [fs]
            WHERE [fs].SpecificationAttributeOptionId NOT IN (
              SELECT psam.SpecificationAttributeOptionId
              FROM dbo.Product_SpecificationAttribute_Mapping psam
              WHERE psam.AllowFiltering = 1 AND psam.ProductId = p.Id
              )
            )
          
        )
      )
    )
  ORDER BY
    CASE WHEN @OrderBy = 0 AND @CategoryCount > 0
    THEN pcm.DisplayOrder END ASC,
    CASE WHEN @OrderBy = 0 AND @ManufacturerId IS NOT NULL AND @ManufacturerId > 0
    THEN pmm.DisplayOrder END ASC,
    CASE WHEN @OrderBy = 0
    THEN p.[Name] END ASC,
    CASE WHEN @OrderBy = 5
    --THEN dbo.[nop_getnotnullnotempty](pl.[Name],p.[Name]) END ASC,
    THEN p.[Name] END ASC,
    CASE WHEN @OrderBy = 10
    THEN pv.Price END ASC,
    CASE WHEN @OrderBy = 15
    THEN p.CreatedOnUtc END DESC

  DROP TABLE #FilteredSpecs

  CREATE TABLE #PageIndex
  (
    [IndexId] int IDENTITY (1, 1) NOT NULL,
    [ProductId] int NOT NULL
  )
  INSERT INTO #PageIndex ([ProductId])
  SELECT ProductId
  FROM #DisplayOrderTmp with (NOLOCK)
  GROUP BY ProductId
  ORDER BY min([Id])

  --total records
  SET @TotalRecords = @@rowcount
  SET ROWCOUNT @RowsToReturn
  
  DROP TABLE #DisplayOrderTmp

  --return products (returned properties should be synchronized with 'Product' entity)
  SELECT  
    p.Id,
    p.Name,
    p.ShortDescription,
    p.FullDescription,
    p.Directions,
    p.Ingredients,
    p.AdminComment,
    p.ProductTemplateId,
    p.ShowOnHomePage,
    p.MetaKeywords,
    p.MetaDescription,
    p.MetaTitle,
    p.SeName,
    p.AllowCustomerReviews,
    p.ApprovedRatingSum,
    p.NotApprovedRatingSum,
    p.ApprovedTotalReviews,
    p.NotApprovedTotalReviews,
    p.Published,
    p.Deleted,
    p.CreatedOnUtc,
    p.UpdatedOnUtc
  FROM
    #PageIndex [pi]
    INNER JOIN Product p with (NOLOCK) on p.Id = [pi].[ProductId]
  WHERE
    [pi].IndexId > @PageLowerBound AND
    [pi].IndexId < @PageUpperBound
  ORDER BY
    IndexId
  
  SET ROWCOUNT 0

  DROP TABLE #PageIndex
END



Nop.Services.Catalog.ProductService.cs

Add in (before SP is called)

string commaSeparatedCategoryIds = "";
                if(categoryId > 0)
                {
                    List<int> categoriesIds = new List<int>();

                    GetCategoriesIds(categoryId, categoriesIds);

                    commaSeparatedCategoryIds = categoryId.ToString();

                    if (categoriesIds.Count > 0)
                    {
                        ((List<int>)categoriesIds).Sort();
                        for (int i = 0; i < categoriesIds.Count; i++)
                        {
                            commaSeparatedCategoryIds += ",";
                            commaSeparatedCategoryIds += categoriesIds[i].ToString();
                        }
                    }

                }


SP, amend categoryId line to be:


new SqlParameter { ParameterName = "CategoryIds", Value = commaSeparatedCategoryIds != null ? (object)commaSeparatedCategoryIds : DBNull.Value, SqlDbType = SqlDbType.NVarChar },


Job done! P.s the code below is the function that creates the list 'categoriesIds' (child id's of the current categoryId so results inc all child categories.


public void GetCategoriesIds(int categoryId, List<int> categoriesIds)
        {
            categoriesIds.Add(categoryId);

            var categories = Nop.Core.Infrastructure.EngineContext.Current.Resolve<ICategoryService>().GetAllCategoriesByParentCategoryId(categoryId);
            foreach (var category in categories)
            {
                GetCategoriesIds(category.Id, categoriesIds);
            }
        }


Perhaps this could be added to 2.4 and can just have an option in the admin to turn on or off, if off then this line won't get called:


GetCategoriesIds(categoryId, categoriesIds);


Cheers!

Dave
12 years ago
P.s remove:

p.Directions,
p.Ingredients,

in the SP, they're custom columns i've added!

Thanks!
12 years ago
Hi inspired

I'm aware you are busy, but I'm just wondering if you could help??

I have generated a pop up display for the product display page. Using the rootpopout.cshtml. I am an absolute novice well to everything and I'm making great headway.

In our Db we are connecting to our company's original Db testing transactional replication. we are connecting certain fields to the Nop Db fields. For example the product stock code is going to be connected to Sku feild.

What my issue is there are fields within the db that are not showing on the front end for example Weight, Height and length even though there is data in them. As mentioned I'm a novice and just wondering how to do so??

All help is highly appreciated.

Kind Regards

Richard.
12 years ago
Hi Richard,

The elements that are missing are from the productvariant table.

It appears that the models/catalog/ProductModel.cs ProductVariantModel() doesn't include this.

If you amend the model and the controller, you'll be able to get these elements into it to use.

Hope this helps!

Thanks,

Dave
12 years ago
Hi Dave

Thank yo for the response

I made the changes in ProductModel.cs as follow's

            public bool ShowWeight { get; set; }
            public string Weight { get; set; }

            public bool ShowLength { get; set; }
            public string Length { get; set; }

            public bool ShowWidth { get; set; }
            public string Width { get; set; }

            public bool ShowHeight { get; set; }
            public string Height { get; set; }

Within the CatalogController.cs region Product what changes would I have to make? If you don't mind me asking?
12 years ago
Hi Richard,

Within: PrepareProductVariantModel

You would assign it like this:

model.ShowWeight = productVariant.Weight

etc.....

That will then give you the weight when you call productVariant.ShowWeight in the view

Thanks,

Dave
12 years ago
Hi Dave

I added the changes in

private ProductModel.ProductVariantModel PrepareProductVariantModel(ProductModel.ProductVariantModel model, ProductVariant productVariant)

model.ShowWeight = _catalogSettings.ShowWeight;
            model.Weight = productVariant.Weight;
            model.ShowLength = _catalogSettings.ShowLength;
            model.Length = productVariant.Length;
            model.ShowHeight = _catalogSettings.ShowHeight;
            model.Height = productVariant.Height;
            model.ShowWidth = _catalogSettings.ShowWidth;
            model.Width = productVariant.Width;

model.Weight = productVariant.Weight;
model.Length = productVariant.Length;
model.Height = productVariant.Height;
model.Width = productVariant.Width;

When Debugging it errors
cannot implicitly convert type 'decimal to String'

Is it nesercary to have the 4 strings above or will these variables display

model.ShowLength = _catalogSettings.ShowLength

Thanks

Richard
12 years ago
Hi

I made the changes to the area as you can see below but its still not displaying which I think is weird I'm not sure If I missed something. I added the it to the productVariantLine.cshtml.

I have changed the product display page to use the root pop out instead of the shared columns. It displays the image sku code and Product Price fine.

CatalogController.cs

[NonAction]
        private ProductModel.ProductVariantModel PrepareProductVariantModel(ProductModel.ProductVariantModel model, ProductVariant productVariant)

model.ShowWeight = _catalogSettings.ShowWeight;
            model.Weight = productVariant.Weight.ToString();
            model.ShowLength = _catalogSettings.ShowLength;
            model.Length = productVariant.Length.ToString();
            model.ShowWidth = _catalogSettings.ShowWidth;
            model.Width = productVariant.Width.ToString();
            model.ShowHeight = _catalogSettings.ShowHeight;
            model.Height = productVariant.Height.ToString();

ProductModel.cs

public class ProductVariantModel : BaseNopEntityModel

public bool ShowWeight { get; set; }
            public string Weight { get; set; }

            public bool ShowLength { get; set; }
            public string Length { get; set; }

            public bool ShowWidth { get; set; }
            public string Width { get; set; }

            public bool ShowHeight { get; set; }
            public string Height { get; set; }


ProductVariantLine.cshtml

@*Weight*@
@if (!String.IsNullOrWhiteSpace(Model.Weight) && Model.ShowWeight)
{
    <div class="Weight">
       @T("Weight")<text>:</text>
       @Model.Weight
    </div>
}  

@*Height*@
@if (!String.IsNullOrWhiteSpace(Model.Height) && Model.ShowHeight)
{
    <div class="Height">
       @T("Packs Per Layer")<text>:</text>
       @Model.Height
    </div>
}  

@*Width*@
@if (!string.IsNullOrWhiteSpace(Model.Width) && Model.ShowWidth)
{
    <div class="Width">
      @T("Layers Per Pallet")<text>:</text>
      @Model.Width
    </div>
}

@*Length*@
@if (!String.IsNullOrWhiteSpace(Model.Length) && Model.ShowLength)
{
    <div class="Length">
      @T("Packs Per Pallet")<text>:</text>
      @Model.Length
    </div>
}

CSS.

.product-variant-line .Weight{color:#3664A5;font-size:1.2em;margin-bottom:.3em;}
.product-variant-line .Height{color:#3664A5;font-size:1.2em;margin-bottom:.3em;}
.product-variant-line .Width{color:#3664A5;font-size:1.2em;margin-bottom:.3em;}
.product-variant-line .Length{color:#3664A5;font-size:1.2em;margin-bottom:.3em;}

.product-variant-line .stock,.product-variant-line .sku,.product-variant-line .manufacturerpartnumber,.product-variant-line .gtin .Weight .Height .Length .Width{color:black;}
12 years ago
Hi, that should be working fine, I presume you've rebuilt the solution?
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.