public virtual async Task <int> DeleteCartItemsAsync( IEnumerable <ShoppingCartItem> cartItems, bool resetCheckoutData = true, bool removeInvalidCheckoutAttributes = false, bool deleteChildCartItems = true) { Guard.NotNull(cartItems, nameof(cartItems)); var customer = cartItems.Select(x => x.Customer).FirstOrDefault(); if (resetCheckoutData && customer != null) { // TODO: (ms) (core) customerService.ResetCheckoutData() is missing //_customerService.ResetCheckoutData(shoppingCartItem.Customer, shoppingCartItem.StoreId); } _db.RemoveRange(cartItems); _requestCache.RemoveByPattern(CartItemsPatternKey); var storeId = cartItems.Select(x => x.StoreId).FirstOrDefault(); var cartItemIds = cartItems.Select(x => x.Id).ToList(); var cartType = cartItems.Select(x => x.ShoppingCartType).FirstOrDefault(); // Delete all child items if (deleteChildCartItems && customer != null) { var childCartItems = await _db.ShoppingCartItems .Where(x => x.CustomerId == customer.Id && x.ParentItemId != null && cartItemIds.Contains(x.ParentItemId.Value) && !cartItemIds.Contains(x.Id)) .BatchDeleteAsync(); } // Validate checkout attributes, removes attributes that require shipping (if cart does not require shipping) if (removeInvalidCheckoutAttributes && cartType == ShoppingCartType.ShoppingCart && customer != null) { var attributeSelection = customer.GenericAttributes.CheckoutAttributes; var attributes = await _checkoutAttributeMaterializer.MaterializeCheckoutAttributesAsync(attributeSelection); var organizedCartItems = await GetCartItemsAsync(customer, storeId : storeId); var attributeIdsToRemove = attributes.GetInvalidShippableAttributesIds(organizedCartItems); attributeSelection.RemoveAttributes(attributeIdsToRemove); customer.GenericAttributes.CheckoutAttributes = attributeSelection; } return(await _db.SaveChangesAsync()); }