From 4c6bd12e7aa9b243bc0c2e7683130c3dd75f86c5 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 21 Jan 2022 11:39:39 +0100 Subject: [PATCH 01/43] Closes #470 The off-canvas cart does not show the tier price (instead of the unit price) when the quantity changes --- .../SmartStore.Web/Controllers/ShoppingCartController.cs | 7 ++++++- .../SmartStore.Web/Scripts/public.offcanvas-cart.js | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs index 103eebeac3..d88a441095 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs @@ -2289,6 +2289,7 @@ public ActionResult UpdateCartItem(int sciItemId, int newQuantity, bool isCartPa var cartHtml = string.Empty; var totalsHtml = string.Empty; + var newItemPrice = string.Empty; if (isCartPage) { @@ -2306,6 +2307,9 @@ public ActionResult UpdateCartItem(int sciItemId, int newQuantity, bool isCartPa PrepareShoppingCartModel(model, cart); cartHtml = this.RenderPartialViewToString("CartItems", model); totalsHtml = this.InvokeAction("OrderTotals", routeValues: new RouteValueDictionary(new { isEditable = true })).ToString(); + + var sci = model.Items.Where(x => x.Id == sciItemId).FirstOrDefault(); + newItemPrice = sci.UnitPrice; } } @@ -2316,7 +2320,8 @@ public ActionResult UpdateCartItem(int sciItemId, int newQuantity, bool isCartPa message = warnings, cartHtml, totalsHtml, - displayCheckoutButtons = true + displayCheckoutButtons = true, + newItemPrice }); } diff --git a/src/Presentation/SmartStore.Web/Scripts/public.offcanvas-cart.js b/src/Presentation/SmartStore.Web/Scripts/public.offcanvas-cart.js index c13fffc21a..5456f933b8 100644 --- a/src/Presentation/SmartStore.Web/Scripts/public.offcanvas-cart.js +++ b/src/Presentation/SmartStore.Web/Scripts/public.offcanvas-cart.js @@ -203,6 +203,9 @@ $(function () { var type = el.data("type"); ShopBar.loadSummary(type, true); el.closest('.tab-pane').find('.sub-total').html(data.SubTotal); + if (data.newItemPrice != "") { + el.closest(".offcanvas-cart-item").find(".unit-price").html(data.newItemPrice); + } } else { $(data.message).each(function (index, value) { From 98c131b1df9b21856cf8a1f9c3ae9609b90ec238 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 21 Jan 2022 16:13:59 +0100 Subject: [PATCH 02/43] Fixed display problem with saved IP addresses --- .../Administration/Controllers/CustomerController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs index 0ab6f35bd4..846cc0ce01 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs @@ -259,7 +259,7 @@ protected virtual void PrepareCustomerModelForEdit(CustomerModel model, Customer model.VatNumberStatusNote = ((VatNumberStatus)customer.VatNumberStatusId).GetLocalizedEnum(Services.Localization, Services.WorkContext); model.CreatedOn = Services.DateTimeHelper.ConvertToUserTime(customer.CreatedOnUtc, DateTimeKind.Utc); model.LastActivityDate = Services.DateTimeHelper.ConvertToUserTime(customer.LastActivityDateUtc, DateTimeKind.Utc); - model.LastIpAddress = model.LastIpAddress; + model.LastIpAddress = customer.LastIpAddress; model.LastVisitedPage = customer.GetAttribute(SystemCustomerAttributeNames.LastVisitedPage); foreach (var tzi in Services.DateTimeHelper.GetSystemTimeZones()) From 38c4680a216e2e908c9a93e604db24398b54f06c Mon Sep 17 00:00:00 2001 From: mgesing Date: Tue, 25 Jan 2022 22:11:56 +0100 Subject: [PATCH 03/43] Fixes stackoverflow when sending NewReturnRequestStoreOwnerNotification --- .../Messages/MessageModelProvider.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs index 6fb1b6a323..cbc11c33a9 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs @@ -1152,7 +1152,7 @@ private TreeNode BuildModelTreePart(string modelName, object in return node; } - private IEnumerable> BuildModelTreePartForClass(object instance) + private IEnumerable> BuildModelTreePartForClass(object instance, HashSet instanceLookup = null) { var type = instance?.GetType(); @@ -1179,9 +1179,21 @@ private IEnumerable> BuildModelTreePartForClass(object } else { - var node = new TreeNode(new ModelTreeMember { Name = prop.Name, Kind = ModelTreeMemberKind.Complex }); - node.AppendRange(BuildModelTreePartForClass(prop.GetValue(instance))); - yield return node; + if (instanceLookup == null) + { + instanceLookup = new HashSet(ReferenceEqualityComparer.Default); + } + + var exists = !type.IsValueType && instanceLookup.Contains(instance); + + if (!exists) + { + instanceLookup.Add(instance); + + var node = new TreeNode(new ModelTreeMember { Name = prop.Name, Kind = ModelTreeMemberKind.Complex }); + node.AppendRange(BuildModelTreePartForClass(prop.GetValue(instance), instanceLookup)); + yield return node; + } } } } From dc3b6178e8968f6c9e9ce459fbdd760d20e73c10 Mon Sep 17 00:00:00 2001 From: mgesing Date: Thu, 27 Jan 2022 10:07:13 +0100 Subject: [PATCH 04/43] MessageModelProvider review --- .../Messages/MessageModelProvider.cs | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs index cbc11c33a9..37045b041f 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs @@ -1177,22 +1177,24 @@ private IEnumerable> BuildModelTreePartForClass(object { yield return new TreeNode(new ModelTreeMember { Name = prop.Name, Kind = ModelTreeMemberKind.Collection }); } - else + else if (pi.PropertyType.IsClass) { if (instanceLookup == null) { - instanceLookup = new HashSet(ReferenceEqualityComparer.Default); + instanceLookup = new HashSet(ReferenceEqualityComparer.Default) { instance }; } - var exists = !type.IsValueType && instanceLookup.Contains(instance); - - if (!exists) + var childInstance = prop.GetValue(instance); + if (childInstance != null) { - instanceLookup.Add(instance); + if (!instanceLookup.Contains(childInstance)) + { + instanceLookup.Add(childInstance); - var node = new TreeNode(new ModelTreeMember { Name = prop.Name, Kind = ModelTreeMemberKind.Complex }); - node.AppendRange(BuildModelTreePartForClass(prop.GetValue(instance), instanceLookup)); - yield return node; + var node = new TreeNode(new ModelTreeMember { Name = prop.Name, Kind = ModelTreeMemberKind.Complex }); + node.AppendRange(BuildModelTreePartForClass(childInstance, instanceLookup)); + yield return node; + } } } } From 5640fef0d2ca6c0b096c448324d4384483080990 Mon Sep 17 00:00:00 2001 From: mgesing Date: Thu, 27 Jan 2022 20:57:19 +0100 Subject: [PATCH 05/43] Ignore selected attributes that are not of type list from finding an associated attribute combination --- .../Catalog/ProductAttributeParser.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs index d6de776ade..6fb44522a1 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs @@ -180,6 +180,11 @@ public virtual void ClearCachedAttributeValues() } public virtual Multimap DeserializeProductVariantAttributes(string attributesXml) + { + return DeserializeAttributesXml(attributesXml, null); + } + + private Multimap DeserializeAttributesXml(string attributesXml, int[] includeAttributesIds = null) { var attrs = new Multimap(); if (String.IsNullOrEmpty(attributesXml)) @@ -195,7 +200,8 @@ public virtual Multimap DeserializeProductVariantAttributes(string string sid = node1.Attribute("ID").Value; if (sid.HasValue()) { - if (int.TryParse(sid, out var id)) + if (int.TryParse(sid, out var id) && + (includeAttributesIds == null || includeAttributesIds.Contains(id))) { // ProductVariantAttributeValue/Value foreach (var node2 in node1.Descendants("Value")) @@ -326,6 +332,11 @@ public virtual bool AreProductAttributesEqual(string attributeXml1, string attri var attributes1 = DeserializeProductVariantAttributes(attributeXml1); var attributes2 = DeserializeProductVariantAttributes(attributeXml2); + return AreProductAttributesEqual(attributes1, attributes2); + } + + private bool AreProductAttributesEqual(Multimap attributes1, Multimap attributes2) + { if (attributes1.Count != attributes2.Count) return false; @@ -383,9 +394,14 @@ public virtual ProductVariantAttributeCombination FindProductVariantAttributeCom if (combinations.Count == 0) return null; + var listTypeValues = ParseProductVariantAttributeValues(attributesXml); + var listTypeAttributesIds = listTypeValues.Select(x => x.ProductVariantAttributeId).ToArray(); + var listTypeAttributesMap = DeserializeAttributesXml(attributesXml, listTypeAttributesIds); + foreach (var combination in combinations) { - bool attributesEqual = AreProductAttributesEqual(combination.AttributesXml, attributesXml); + var combinationAttributesMap = DeserializeProductVariantAttributes(combination.AttributesXml); + bool attributesEqual = AreProductAttributesEqual(combinationAttributesMap, listTypeAttributesMap); if (attributesEqual) return _productAttributeService.GetProductVariantAttributeCombinationById(combination.Id); } From 7b7fcdbc3f3d111a27d958434868c4bf760e897e Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 31 Jan 2022 16:14:14 +0100 Subject: [PATCH 06/43] Minor fix --- .../en/RecurringPaymentCancelled.StoreOwnerNotification.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/App_Data/EmailTemplates/en/RecurringPaymentCancelled.StoreOwnerNotification.xml b/src/Presentation/SmartStore.Web/App_Data/EmailTemplates/en/RecurringPaymentCancelled.StoreOwnerNotification.xml index d3ee97313d..e14856fd6f 100644 --- a/src/Presentation/SmartStore.Web/App_Data/EmailTemplates/en/RecurringPaymentCancelled.StoreOwnerNotification.xml +++ b/src/Presentation/SmartStore.Web/App_Data/EmailTemplates/en/RecurringPaymentCancelled.StoreOwnerNotification.xml @@ -15,7 +15,7 @@

- View payment + View payment

From db1307ff1d93404b9100409e638ff409c0d4454a Mon Sep 17 00:00:00 2001 From: mgesing Date: Wed, 2 Feb 2022 21:40:22 +0100 Subject: [PATCH 07/43] Minor fix when adding a product variant attribute --- .../Administration/Controllers/ProductController.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index a195f095ed..4128b0ef51 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -2970,18 +2970,21 @@ public ActionResult ProductVariantAttributeInsert(GridCommand command, ProductMo { ProductId = model.ProductId, // Use ProductAttribute property (not ProductAttributeId) because appropriate property is stored in it. - ProductAttributeId = int.Parse(model.ProductAttribute), + ProductAttributeId = model.ProductAttribute.ToInt(), TextPrompt = model.TextPrompt, CustomData = model.CustomData, IsRequired = model.IsRequired, // Use AttributeControlType property (not AttributeControlTypeId) because appropriate property is stored in it. - AttributeControlTypeId = int.Parse(model.AttributeControlType), + AttributeControlTypeId = model.AttributeControlType.ToInt((int)AttributeControlType.DropdownList), DisplayOrder = model.DisplayOrder1 }; try { - _productAttributeService.InsertProductVariantAttribute(pva); + if (pva.ProductAttributeId != 0) + { + _productAttributeService.InsertProductVariantAttribute(pva); + } } catch (Exception ex) { From acb9eed4907f9b82436859a98f97da2e8e9020ca Mon Sep 17 00:00:00 2001 From: mgesing Date: Mon, 14 Feb 2022 20:18:56 +0100 Subject: [PATCH 08/43] Fixes browse-file-button in link builder out of function --- .../SmartStore.Web/Views/Shared/EditorTemplates/Link.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Link.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Link.cshtml index 694a1a0788..41d0b05cdb 100644 --- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Link.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Link.cshtml @@ -118,7 +118,7 @@ @if (allowedTypes.Contains(LinkType.File)) {