Developer forum

Forum » Ecommerce - Standard features » Oderline gets duplicated in cart (should increase quantity)

Oderline gets duplicated in cart (should increase quantity)

Aki Ruuskanen
Aki Ruuskanen
Reply

Hi,

I have a solution where, when adding the same product to cart twice, the orderline gets "duplicated" instead of just increasing quantity. The part that I cant figure out is that this only happends in production. In our staging (and in my local) enviroment the quantity get increased. 

When clicking the links below and then reloading again the production enviroment will have two rows in cart and the staging will have one with quantity of 2. I think I have seen this before but cannot remember what causes this.  

Production:

https://www.magnusson-freij.se/kassan?productid=0113104500&cartcmd=add&quantity=1&UnitID=ST&redirect=false

Staging:

http://mf94.staging.softgear.se/kassan?productid=0113104500&cartcmd=add&quantity=1&UnitID=ST&redirect=false

Does anyone have any ideas?

Regards / Aki

 


Replies

 
Nicolai Pedersen
Reply

Hi Aki

There are a lot of things in play when deciding if orderlines should be merged or not. I.e. variantid, unit, custom orderline fields etc. So I would find the 2 orderlines in the database and locate the difference as that would give you a pointer.

For reference and problem location, please refer to this code that holds the logic for when orderlines are merged or not.

BR NIcolai

        Public Function CanBeMerged(orderLine As OrderLine, another As OrderLine) As Boolean
            If orderLine Is Nothing OrElse another Is Nothing Then
                Return False
            End If

            If (orderLine.HasType(OrderLineType.PointProduct) AndAlso another.HasType(OrderLineType.PointProduct)) Then
                Return Not (IsNothing(orderLine.RewardId) OrElse IsNothing(orderLine.RewardPoints) OrElse IsNothing(another.RewardId) OrElse IsNothing(another.RewardPoints) OrElse
                    orderLine.RewardId.Value <> another.RewardId.Value OrElse String.Equals(orderLine.ProductId, another.ProductId, StringComparison.Ordinal) OrElse
                    String.Equals(If(orderLine.ProductVariantId, String.Empty), If(another.ProductVariantId, String.Empty), StringComparison.Ordinal) OrElse
                    String.Equals(orderLine.Product.LanguageId, another.Product.LanguageId, StringComparison.Ordinal))
            End If
            If orderLine.HasType(OrderLineType.PointProduct) OrElse another.HasType(OrderLineType.PointProduct) Then
                Return False
            End If

            If orderLine.Product.Type = ProductType.GiftCard OrElse another.Product.Type = ProductType.GiftCard OrElse
                (orderLine.HasType(OrderLineType.Discount) AndAlso Not String.IsNullOrEmpty(orderLine.GiftCardCode)) OrElse
                (another.HasType(OrderLineType.Discount) AndAlso Not String.IsNullOrEmpty(another.GiftCardCode)) Then
                Return False
            End If

            If (orderLine.HasType(OrderLineType.ProductDiscount) AndAlso Not another.HasType(OrderLineType.ProductDiscount)) OrElse
                (Not orderLine.HasType(OrderLineType.ProductDiscount) AndAlso another.HasType(OrderLineType.ProductDiscount)) Then
                Return False
            End If

            If Not orderLine.Product.Type = ProductType.Bom Then
                Return String.Equals(orderLine.Id, another.Id, StringComparison.Ordinal) OrElse
                       (String.Equals(orderLine.Product.Id, another.Product.Id, StringComparison.Ordinal) AndAlso
                        String.Equals(If(orderLine.ProductVariantId, String.Empty), If(another.ProductVariantId, String.Empty), StringComparison.Ordinal) AndAlso
                        String.Equals(If(orderLine.UnitId, String.Empty), If(another.UnitId, String.Empty), StringComparison.Ordinal) AndAlso
                        orderLine.OrderLineFieldValues.Equals(another.OrderLineFieldValues)
                       )
            End If

            For Each thisBomItem As OrderLine In orderLine.BomOrderLines
                Dim matchFound As Boolean = False
                For Each otherBomItem As OrderLine In another.BomOrderLines
                    If CanBeMerged(thisBomItem, otherBomItem) Then
                        matchFound = True
                    End If
                Next
                If Not matchFound Then
                    Return False
                End If
            Next

            Return String.Equals(orderLine.Id, another.Id, StringComparison.Ordinal) OrElse
                    (String.Equals(orderLine.Product.Id, another.Product.Id, StringComparison.Ordinal) AndAlso
                    String.Equals(If(orderLine.ProductVariantId, String.Empty), If(another.ProductVariantId, String.Empty), StringComparison.Ordinal) AndAlso
                    String.Equals(orderLine.UnitId, another.UnitId, StringComparison.Ordinal) AndAlso
                    orderLine.OrderLineFieldValues.Equals(another.OrderLineFieldValues))
        End Function

 
Aki Ruuskanen
Aki Ruuskanen
Reply

Hi,

Yes, checked the Orderlines in DB they are equal.

VariantID and DiscountID is NULL.

UnitID is equal ("ST").

OrderlinBOM is 0. 

FieldValues are "<OrderLineFieldValueCollection><OrderLineFieldValue><OrderLineFieldSystemName>Markning</OrderLineFieldSystemName><Value></Value></OrderLineFieldValue></OrderLineFieldValueCollection>"

frown

 

 

 
Nicolai Pedersen
Reply

Can you give us a dump of all columns of the 2 rows?

 
Aki Ruuskanen
Aki Ruuskanen
Reply

Here comes. 

 
Nicolai Pedersen
Reply

Do you have custom add to cart feature somehow?

 
Aki Ruuskanen
Aki Ruuskanen
Reply

Yes, there is a Notifications.Ecommerce.Cart.Line.Added

Besides code that has been there for ages we do a HTMLDecode on the UnitID. 

orderline.UnitId = WebUtility.HtmlDecode(orderline.UnitId);

It's still the same code I have locally and on the staging server where the cart lines behave as the should. 

/Aki

 
Aki Ruuskanen
Aki Ruuskanen
Reply

Hi,

I have upgraded the solution to 9.6.5 (locally and on the production server) and deployed our custom code again. The problem is still there. 

I have stripped down the "CanBeMerged" method to the part that applies to this situation. Looks like it compares the IDs of the orderlines? How does this work? The orderlines in my case have differens IDs and that is the problem. :) 

Return String.Equals(orderLine.Id, another.Id, StringComparison.Ordinal) OrElse
(String.Equals(orderLine.Product.Id, another.Product.Id, StringComparison.Ordinal) AndAlso
String.Equals(If(orderLine.ProductVariantId, String.Empty), If(another.ProductVariantId, String.Empty), StringComparison.Ordinal) AndAlso
String.Equals(orderLine.UnitId, another.UnitId, StringComparison.Ordinal) AndAlso
orderLine.OrderLineFieldValues.Equals(another.OrderLineFieldValues))

/Aki

 
Nicolai Pedersen
Reply

Hf Aki

If the ids of 2 lines are equal, they are "CanBeMerged". OrElse, if productid AND VariantID AND UnitID AND customOrderlineFields are equal, they can also be merged.

I think the conditional is very self explanatory...

BR Nicolai

 
Aki Ruuskanen
Aki Ruuskanen
Reply

Yes they are. smiley

I'm just wondering what happends before this method is called. In my case Productid AND VariantID AND UnitID AND customOrderlineFields are equal but the IDs are not. What decides that a new orderline gets a new ID?

/Aki

 

You must be logged in to post in the forum