SKU problem

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
13 years ago
Correct me if I am wrong but a SKU (Stock keeping unit) is a referance to the actual item as stocked in your warehouse or any uniquelly billable item.

So using the sample data the product Adobe Photoshop Elements might have a SKU of "ADOB-PE7" which is how it is "stocked in the warehouse" where as the adidas shoes would be something like this:

(Manufacturer - Model - Colour- Size)
"ADID-CSH7-BLUE-8" = White/Blue size 8
"ADID-CSH7-BLUE-9" = White/Blue size 9
"ADID-CSH7-BLUE-10" = White/Blue size 10 etc....

in 1.8 you do keep and track the different stock records for each combination but not the SKU of each unique combination,

I am writing a webservice so that our current warehouse application updates the webstore with the correct stock available however I need the unique SKU as it is it is stocked in the warehouse to relate to a stock value in the website.

Any thoughts
13 years ago
I have the same problems for shoes. Each size has a different SKU. I am very surprised that such a good product as Nop missed that point
13 years ago
I found a work around for it by making a small modification to the code and database, I would like to submit the modification idea to nop for consideration so that it is incorporated into future release.

basically i added a column for SKU to the Nop_ProductVariantAttributeCombination table and modified the code to add the textbox to the same page as the stock is entered for the variant combination. So that when you add a new variation you can give it a value for SKU as well as the stock value.
13 years ago
Can you show your modifications?
13 years ago
sure, i will just double check all the changes I made and will post them here tommorow
13 years ago
I'm looking forward to that aswell. I also agree about how strange it is that nopCommerce doesnt support sku-modifications on size/color-level.

But still, i love nopCommerce!
13 years ago
Please note this is TEST code it not fully finished and tested and I need to find out anywhere these code changes effect other than the required places specifically the import and export manager etc.., so please review and comment. (Oh yes and backup the originals first)

First add the new SKU column to the Nop_ProductVariantAttributeCombination table by running the following sql on your database.

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Nop_ProductVariantAttributeCombination ADD
  SKU nvarchar(50) NULL
GO
ALTER TABLE dbo.Nop_ProductVariantAttributeCombination SET (LOCK_ESCALATION = TABLE)
GO
COMMIT


next find and modify the following functions in \Libraries\Nop.BusinessLogic\Products\Attributes\ProductAttributeManager.cs to add the value for the SKU

public static ProductVariantAttributeCombination InsertProductVariantAttributeCombination(int productVariantId,
            string attributesXml,
            int stockQuantity,
            bool allowOutOfStockOrders,
            string SKU)
        {
            var context = ObjectContextHelper.CurrentObjectContext;

            var combination = context.ProductVariantAttributeCombinations.CreateObject();
            combination.ProductVariantId = productVariantId;
            combination.AttributesXml = attributesXml;
            combination.StockQuantity = stockQuantity;
            combination.AllowOutOfStockOrders = allowOutOfStockOrders;
            combination.SKU = SKU;

            context.ProductVariantAttributeCombinations.AddObject(combination);
            context.SaveChanges();

            return combination;


and


public static ProductVariantAttributeCombination UpdateProductVariantAttributeCombination(int productVariantAttributeCombinationId,
            int productVariantId,
            string attributesXml,
            int stockQuantity,
            bool allowOutOfStockOrders,
            string SKU)
        {
            var combination = GetProductVariantAttributeCombinationById(productVariantAttributeCombinationId);
            if (combination == null)
                return null;

            var context = ObjectContextHelper.CurrentObjectContext;
            if (!context.IsAttached(combination))
                context.ProductVariantAttributeCombinations.Attach(combination);

            combination.ProductVariantId = productVariantId;
            combination.AttributesXml = attributesXml;
            combination.StockQuantity = stockQuantity;
            combination.AllowOutOfStockOrders = allowOutOfStockOrders;
            combination.SKU = SKU;
            context.SaveChanges();

            return combination;



next \Libraries\Nop.BusinessLogic\Products\Attributes\ProductVariantAttributeCombination.cs

add the SKU to the class in the properties section


/// <summary>
        /// Gets or sets a SKU (NEW)
        /// </summary>
        public string SKU { get; set; }


next find and modify the following in \Libraries\Nop.BusinessLogic\Products\ProductManager.cs to read

foreach (var combination in ProductAttributeManager.GetAllProductVariantAttributeCombinations(productVariant.ProductVariantId))
                    {
                        ProductAttributeManager.InsertProductVariantAttributeCombination(productVariantCopy.ProductVariantId,
                              combination.AttributesXml,
                              combination.StockQuantity,
                              combination.AllowOutOfStockOrders,
                              combination.SKU
                              );
                    }

and

case ManageInventoryMethodEnum.ManageStockByAttributes:
                    {
                        var combination = ProductAttributeManager.FindProductVariantAttributeCombination(productVariant.ProductVariantId, attributesXml);
                        if (combination != null)
                        {
                            int newStockQuantity = 0;
                            if (decrease)
                                newStockQuantity = combination.StockQuantity - quantity;
                            else
                                newStockQuantity = combination.StockQuantity + quantity;

                            combination = ProductAttributeManager.UpdateProductVariantAttributeCombination(combination.ProductVariantAttributeCombinationId,
                                combination.ProductVariantId, combination.AttributesXml, newStockQuantity, combination.AllowOutOfStockOrders, combination.SKU);
                        }
                    }


next modify \Administration\Modules\ProductVariantAttributes.ascx
[code]
<ajaxToolkit:TabPanel runat="server" ID="pnlComb" HeaderText="<% $NopResources:Admin.ProductAdd.AttributeCombinations %>">
                <ContentTemplate>
                    <asp:Panel runat="server" ID="pnlCombinations">
                        <div>
                            <asp:GridView ID="gvCombinations" runat="server" AutoGenerateColumns="false" DataKeyNames="ProductVariantAttributeCombinationId"
                                OnRowDeleting="gvCombinations_RowDeleting" OnRowDataBound="gvCombinations_RowDataBound"
                                OnRowCommand="gvCombinations_RowCommand" Width="100%">
                                <Columns>
                                    <asp:TemplateField HeaderText="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.Attributes %>"
                                        ItemStyle-Width="50%">
                                        <ItemTemplate>
                                            <asp:Label runat="server" ID="lblAttributes"></asp:Label>
                                            <br />
                                            <asp:Label runat="server" ID="lblWarnings" Style="color: Red;"></asp:Label>
                                            <asp:HiddenField ID="hfProductVariantAttributeCombinationId" runat="server" Value='<%# Eval("ProductVariantAttributeCombinationId") %>' />
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.StockQuantity %>"
                                        ItemStyle-Width="15%">
                                        <ItemTemplate>
                                            <nopCommerce:NumericTextBox runat="server" CssClass="adminInput" Width="50px" ID="txtStockQuantity"
                                                Value='<%# Eval("StockQuantity") %>' RequiredErrorMessage="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.StockQuantity.RequiredErrorMessage %>"
                                                RangeErrorMessage="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.StockQuantity.RangeErrorMessage %>"
                                                ValidationGroup="UpdateProductVariantAttributeCombination" MinimumValue="-99999"
                                                MaximumValue="99999"></nopCommerce:NumericTextBox>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="<% $NopResources:Admin.ProductInfo.SKU %>"
                                        ItemStyle-Width="15%">
                                        <ItemTemplate>
                                        <asp:TextBox runat="server" CssClass="adminInput" ID="txtSKU" Value='<%# Eval("SKU") %>'></asp:TextBox>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.AllowOutOfStockOrders %>"
                                        ItemStyle-Width="15%">
                                        <ItemTemplate>
                                            <asp:CheckBox ID="cbAllowOutOfStockOrders" runat="server" Checked='<%# Eval("AllowOutOfStockOrders") %>' />
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.Update %>"
                                        HeaderStyle-HorizontalAlign="Center" ItemStyle-Width="10%" ItemStyle-HorizontalAlign="Center">
                                        <ItemTemplate>
                                            <asp:Button ID="btnUpdate" runat="server" CssClass="adminButton" Text="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.Update %>"
                                                ValidationGroup="UpdateProductVariantAttributeCombination" CommandName="UpdateProductVariantAttributeCombination" />
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.Delete %>"
                                        HeaderStyle-HorizontalAlign="Center" ItemStyle-Width="10%" ItemStyle-HorizontalAlign="Center">
                                        <ItemTemplate>
                                            <asp:Button ID="btnDelete" runat="server" CssClass="adminButton" Text="<% $NopResources:Admin.ProductVariantAttributes.CombinationsGrid.Delete %>"
                                                CausesValidation="false" CommandName="Delete" />
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                </Columns>
                            </asp:GridView>
                        </div>
                        <div style="margin: 10px 0px 10px 0px;">
                            <%=GetLocaleResourceString("Admin.ProductVariantAttributes.Combinations.SelectCombination")%>
                        </div>
                        <div style="border: 1px dashed #2F4F4F; padding: 15px; margin: 10px 0px 10px 0px;">
                            <nopCommerce:SelectProductAttributes ID="ctrlSelectProductAttributes" runat="server"
                                HidePrices="true"></nopCommerce:SelectProductAttributes>
                            <asp:Panel runat="server" ID="pnlCombinationWarningsr" EnableViewState="false" Visible="false"
                                class="messageBox messageBoxError">
                                <asp:Literal runat="server" ID="lCombinationWarnings" EnableViewState="false" />
                            </asp:Panel>
                        </div>
                        <div>
                            <table class="adminContent">
                                <tr>
                                    <td class="adminTitle">
                                        <nopCommerce:ToolTipLabel runat="server" ID="lblStockQuantity" Text="<% $NopResources:Admin.ProductVariantAttributes.Combinations.StockQuantity %>"
                                            ToolTip="<% $NopResources:Admin.ProductVariantAttributes.Combinations.StockQuantity.Tooltip %>"
                                            ToolTipImage="~/Administration/Common/ico-help.gif" />
                                    </td>
                                    <td class="adminData">
                                        <nopCommerce:NumericTextBox runat="server" CssClass="adminInput" ID="txtStockQuantity"
                                            RequiredErrorMessage="<% $NopResources:Admin.ProductVariantAttributes.Combinations.StockQuantity.RequiredErrorMessage %>"
                                            MinimumValue="-999999" MaximumValue="999999" Value="10000" RangeErrorMessage="<% $NopResources:Admin.ProductVariantAttributes.Combinations.StockQuantity.RangeErrorMessage %>"
                                            ValidationGroup="NewProductVariantAttributeCombination"></nopCommerce:NumericTextBox>
                                    </td>
                                </tr>
                                <tr>
                                    <td class="adminTitle">
                                        <nopCommerce:ToolTipLabel runat="server" ID="lblAllowOutOfStockOrders" Text="<% $NopResources:Admin.ProductVariantAttributes.Combinations.AllowOutOfStockOrders %>"
                                            ToolTip="<% $NopResources:Admin.ProductVariantAttributes.Combinations.AllowOutOfStockOrders.Tooltip %>"
                                            ToolTipImage="~/Administration/Common/ico-help.gif" />
                                    </td>
                                    <td class="adminData">
                                        <asp:CheckBox ID="cbAllowOutOfStockOrders" runat="server"></asp:CheckBox>
                                    </td>
                                </tr>
                                <tr>
                                    <td class="adminTitle">
                                        <nopCommerce:ToolTipLabel runat="server" ID="ToolTipLabel1" Text="SKU"
                                            ToolTip=""
                                            ToolTipImage="~/Administration/Common/ico-help.gif" />
                                    </td>
                                    <td class="adminData">
                                        <asp:TextBox ID="txtNewSKU" runat="server"></asp:TextBox>
                                    </td>
                                </tr>
                                <tr>
                                    <td colspan="2" align="left">
                                        <asp:Button runat="server" ID="btnNewProductVariantAttributeCombination" CssClass="adminButton"
                                            Text="<% $NopResources:Admin.ProductVariantAttributes.Combinations.AddNewButton.Text %>"
                                            ValidationGroup="NewProductVariantAttributeCombination" OnClick="btnNewProductVariantAttributeCombination_Click" />
                                    </td>
                                </tr>
                            </table>
                        </div>
                    </asp:Panel>
                </ContentTemplate>
            </ajaxToolkit
13 years ago
the rest


next \Administration\Modules\ProductVariantAttributes.ascx.cs

protected void gvProductVariantAttributes_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            if (e.CommandName == "UpdateProductVariantAttribute")
            {
                int index = Convert.ToInt32(e.CommandArgument);
                GridViewRow row = gvProductVariantAttributes.Rows[index];

                HiddenField hfProductVariantAttributeId = row.FindControl("hfProductVariantAttributeId") as HiddenField;
                DropDownList ddlProductAttribute = row.FindControl("ddlProductAttribute") as DropDownList;
                TextBox txtTextPrompt = row.FindControl("txtTextPrompt") as TextBox;
                TextBox txtSKU = row.FindControl("txtSKU") as TextBox;
                CheckBox cbIsRequired = row.FindControl("cbIsRequired") as CheckBox;
                DropDownList ddlAttributeControlType = row.FindControl("ddlAttributeControlType") as DropDownList;
                NumericTextBox txtDisplayOrder = row.FindControl("txtDisplayOrder") as NumericTextBox;

                int productVariantAttributeId = int.Parse(hfProductVariantAttributeId.Value);
                int productAttributeId = int.Parse(ddlProductAttribute.SelectedItem.Value);
                string textPrompt = txtTextPrompt.Text;
                string SKU = txtSKU.Text;
                bool isRequired = cbIsRequired.Checked;
                AttributeControlTypeEnum attributeControlType = (AttributeControlTypeEnum)Enum.ToObject(typeof(AttributeControlTypeEnum), int.Parse(ddlAttributeControlType.SelectedItem.Value));
                int displayOrder = txtDisplayOrder.Value;

                ProductVariantAttribute productVariantAttribute = ProductAttributeManager.GetProductVariantAttributeById(productVariantAttributeId);

                if (productVariantAttribute != null)
                    ProductAttributeManager.UpdateProductVariantAttribute(productVariantAttribute.ProductVariantAttributeId,
                       productVariantAttribute.ProductVariantId, productAttributeId, textPrompt,
                       isRequired, attributeControlType, displayOrder);

                BindAttributes();
                BindCombinations();
                RefreshSelectCombinationControl();
            }
        }


and

protected void btnNewProductVariantAttributeCombination_Click(object sender, EventArgs e)
        {
            try
            {
                ProductVariant productVariant = ProductManager.GetProductVariantById(this.ProductVariantId);
                if (productVariant != null)
                {
                    string attributes = ctrlSelectProductAttributes.SelectedAttributes;
                    int stockQuantity = txtStockQuantity.Value;
                    string SKU = txtNewSKU.Text;
                    bool allowOutOfStockOrders = cbAllowOutOfStockOrders.Checked;

                    List<string> warnings = ShoppingCartManager.GetShoppingCartItemAttributeWarnings(ShoppingCartTypeEnum.ShoppingCart,
                            productVariant.ProductVariantId, attributes, 1, false);
                    if (warnings.Count > 0)
                    {
                        StringBuilder warningsSb = new StringBuilder();
                        for (int i = 0; i < warnings.Count; i++)
                        {
                            warningsSb.Append(Server.HtmlEncode(warnings[i]));
                            if (i != warnings.Count - 1)
                            {
                                warningsSb.Append("<br />");
                            }
                        }

                        pnlCombinationWarningsr.Visible = true;
                        lCombinationWarnings.Text = warningsSb.ToString();
                    }
                    else
                    {
                        var combination = ProductAttributeManager.InsertProductVariantAttributeCombination(productVariant.ProductVariantId,
                            attributes,
                            stockQuantity,
                            allowOutOfStockOrders,
                            SKU);
                    }
                    BindCombinations();
                }
            }
            catch (Exception exc)
            {
                processAjaxError(exc);
            }
        }


and

protected void gvCombinations_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            if (e.CommandName == "UpdateProductVariantAttributeCombination")
            {
                int index = Convert.ToInt32(e.CommandArgument);
                GridViewRow row = gvCombinations.Rows[index];

                HiddenField hfProductVariantAttributeCombinationId = row.FindControl("hfProductVariantAttributeCombinationId") as HiddenField;
                Label lblAttributes = row.FindControl("lblAttributes") as Label;
                Label lblWarnings = row.FindControl("lblWarnings") as Label;
                NumericTextBox txtStockQuantity = row.FindControl("txtStockQuantity") as NumericTextBox;
                TextBox txtSKU = row.FindControl("txtSKU") as TextBox;
                CheckBox cbAllowOutOfStockOrders = row.FindControl("cbAllowOutOfStockOrders") as CheckBox;

                int productVariantAttributeCombinationId = int.Parse(hfProductVariantAttributeCombinationId.Value);
                int stockQuantity = txtStockQuantity.Value;
                string SKU = txtSKU.Text;
                bool allowOutOfStockOrders = cbAllowOutOfStockOrders.Checked;

                var combination = ProductAttributeManager.GetProductVariantAttributeCombinationById(productVariantAttributeCombinationId);

                if (combination != null)
                    ProductAttributeManager.UpdateProductVariantAttributeCombination(combination.ProductVariantAttributeCombinationId,
                       combination.ProductVariantId, combination.AttributesXml,
                       stockQuantity, allowOutOfStockOrders, SKU);

                BindCombinations();
            }
        }



I think thats it, could someone from nop please check this and comment,
13 years ago
Thanks, I tried copying and pasting, but the nop Forum doesn't add cr+lf characters. Could I ask you to send those modded files to "ajhvdb (at) gmail.com".

I will then use "Beyond Compare" to copy your mods..
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.