private StockStatusCalculatorResult GetStockStatus(Variant variant, string sourceId) { var calculatorArgs = new StockStatusCalculatorArgs { Date = HttpContext.Current?.Timestamp ?? DateTime.UtcNow, UserSystemId = SecurityToken.CurrentSecurityToken.UserID, WebSiteSystemId = _cartAccessor.Cart.OrderCarrier.WebSiteID, SourceId = sourceId, CountrySystemId = _cartAccessor.Cart.OrderCarrier.CountryID }; var calculatorItemArgs = new StockStatusCalculatorItemArgs { VariantSystemId = variant.SystemId, Quantity = decimal.One }; return(_stockStatusCalculator.GetStockStatuses(calculatorArgs, calculatorItemArgs).TryGetValue(variant.SystemId, out StockStatusCalculatorResult calculatorResult) ? calculatorResult : null); }
private StockStatusCalculatorResult GetStockStatus(Variant variant, string sourceId) { var cartContext = _cartContextAccessor.CartContext; var calculatorArgs = new StockStatusCalculatorArgs { UserSystemId = _securityContextService.GetIdentityUserSystemId().GetValueOrDefault(), SourceId = sourceId, CountrySystemId = _countryService.Get(cartContext?.CountryCode)?.SystemId }; var calculatorItemArgs = new StockStatusCalculatorItemArgs { VariantSystemId = variant.SystemId, Quantity = decimal.One }; return(_stockStatusCalculator.GetStockStatuses(calculatorArgs, calculatorItemArgs).TryGetValue(variant.SystemId, out StockStatusCalculatorResult calculatorResult) ? calculatorResult : null); }
/// <summary> /// Validates the specified order carrier. /// </summary> /// <param name="orderCarrier"> The order carrier. </param> /// <param name="checkoutFlowInfo"> The checkout flow info. </param> public void Validate(OrderCarrier orderCarrier, CheckoutFlowInfo checkoutFlowInfo) { if (orderCarrier.OrderRows.Count > 0) { var personId = orderCarrier.CustomerInfo?.PersonID ?? _securityToken.UserID; var articlesPurchased = orderCarrier.OrderRows .Where(o => !o.CarrierState.IsMarkedForDeleting && !o.IsAutoGenerated) .GroupBy(o => o.ArticleNumber) .Select(g => new { ArticleNumber = g.Key, Quantity = g.Sum(p => p.Quantity) }); var outOfStocksProducts = new List <string>(); var notEnoughInStocksProducts = new List <string>(); foreach (var item in articlesPurchased) { var article = _variantService.Get(item.ArticleNumber); if (article != null) { StockStatusCalculatorResult stockStatus; _stockStatusCalculator.GetStockStatuses(new StockStatusCalculatorArgs { Date = HttpContext.Current.Timestamp, UserSystemId = personId, WebSiteSystemId = orderCarrier.WebSiteID, CountrySystemId = orderCarrier.CountryID }, new StockStatusCalculatorItemArgs { VariantSystemId = article.SystemId, Quantity = item.Quantity }).TryGetValue(article.SystemId, out stockStatus); //if stock status is not returned or the actual stock level is zero or below. if (stockStatus == null || stockStatus.InStockQuantity.GetValueOrDefault() <= decimal.Zero) { //remove the order row from order carrier. foreach (var orderRow in orderCarrier.OrderRows.Where(x => x.ArticleNumber == article.Id).ToList()) { //we have to call edit order row to handle the correct removal from delivery, and to provide access to extension point. _moduleECommerce.CheckoutFlow.EditOrderRow(orderCarrier, orderRow.ID, 0, string.Empty, 0, _moduleECommerce.AdminToken); Cart.UpdateRowQuantity(orderRow.ID, 0); } outOfStocksProducts.Add(article.GetDisplayName(CultureInfo.CurrentCulture)); } else { var existingStocks = stockStatus.InStockQuantity.GetValueOrDefault(); var notEnoughStocks = false; foreach (var orderRow in orderCarrier.OrderRows .Where(x => x.ArticleNumber == article.Id && !x.CarrierState.IsMarkedForDeleting) .OrderByDescending(x => x.IsAutoGenerated) .ToList() ) { if (existingStocks >= decimal.Zero) { if (orderRow.Quantity > existingStocks) { //we have to call edit order row to handle the correct removal from delivery, and to provide access to extension point. var changedRow = _moduleECommerce.CheckoutFlow.EditOrderRow(orderCarrier, orderRow.ID, existingStocks, orderRow.Comments, orderRow.DiscountPercentage, _moduleECommerce.AdminToken); notEnoughStocks = true; existingStocks -= changedRow.Quantity; Cart.UpdateRowQuantity(changedRow.ID, changedRow.Quantity); } else { existingStocks -= orderRow.Quantity; } } else { //we have to call edit order row to handle the correct removal from delivery, and to provide access to extension point. _moduleECommerce.CheckoutFlow.EditOrderRow(orderCarrier, orderRow.ID, 0, string.Empty, 0, _moduleECommerce.AdminToken); notEnoughStocks = true; Cart.UpdateRowQuantity(orderRow.ID, 0); } } if (notEnoughStocks) { notEnoughInStocksProducts.Add(article.GetDisplayName(CultureInfo.CurrentCulture)); } } } } if (outOfStocksProducts.Count > 0 || notEnoughInStocksProducts.Count > 0) { Cart.UpdateChangedRows(); var sb = new StringBuilder(); if (outOfStocksProducts.Count > 0) { var outOfStocksMsg = "accelerator.validation.product.outofstock".AsAngularResourceString(); outOfStocksProducts.ForEach(x => sb.AppendFormat(outOfStocksMsg, x)); } if (notEnoughInStocksProducts.Count > 0) { var notEnoughInStocksProductsMsg = "accelerator.validation.product.notenoughinstock".AsAngularResourceString(); notEnoughInStocksProducts.ForEach(x => sb.AppendFormat(notEnoughInStocksProductsMsg, x)); } throw new PreOrderValidationException(sb.ToString()); } } }
public override async Task <ValidationResult> ValidateAsync(ValidateCartContextArgs entity, ValidationMode validationMode) { var result = new ValidationResult(); var order = entity.Cart.Order; if (order.Rows.Count > 0) { var personId = order.CustomerInfo?.PersonSystemId ?? _securityContextService.GetIdentityUserSystemId() ?? Guid.Empty; var countryId = _countryService.Get(order.CountryCode)?.SystemId; var updatedItems = new List <AddOrUpdateCartItemArgs>(); var outOfStocksProducts = new List <string>(); var notEnoughInStocksProducts = new List <string>(); foreach (var row in order.Rows.Where(x => x.OrderRowType == OrderRowType.Product)) { var variant = _variantService.Get(row.ArticleNumber); if (variant != null) { _stockStatusCalculator.GetStockStatuses(new StockStatusCalculatorArgs { UserSystemId = personId, CountrySystemId = countryId }, new StockStatusCalculatorItemArgs { VariantSystemId = variant.SystemId, Quantity = row.Quantity }).TryGetValue(variant.SystemId, out var stockStatus); var existingStocks = stockStatus?.InStockQuantity.GetValueOrDefault(); //If stock status is not returned or the actual stock level is zero or below. if (stockStatus == null || existingStocks <= decimal.Zero) { //Remove the order row from the shopping cart. updatedItems.Add(new AddOrUpdateCartItemArgs { ArticleNumber = row.ArticleNumber, Quantity = 0, ConstantQuantity = true, }); outOfStocksProducts.Add(variant.Localizations[CultureInfo.CurrentCulture].Name ?? variant.Id); } else { if (row.Quantity > existingStocks) { //Update the order row with available amount in stock. updatedItems.Add(new AddOrUpdateCartItemArgs { ArticleNumber = row.ArticleNumber, Quantity = existingStocks.Value, ConstantQuantity = true, }); notEnoughInStocksProducts.Add(variant.Localizations[CultureInfo.CurrentCulture].Name ?? variant.Id); } } } } if (updatedItems.Count > 0) { foreach (var item in updatedItems) { await _cartContextAccessor.CartContext.AddOrUpdateItemAsync(item); } await _cartContextAccessor.CartContext.CalculatePaymentsAsync(); } if (outOfStocksProducts.Count > 0 || notEnoughInStocksProducts.Count > 0) { var sb = new StringBuilder(); if (outOfStocksProducts.Count > 0) { outOfStocksProducts.ForEach(x => sb.AppendFormat("sales.validation.product.outofstock".AsWebsiteText(), x)); } if (notEnoughInStocksProducts.Count > 0) { notEnoughInStocksProducts.ForEach(x => sb.AppendFormat("sales.validation.product.notenoughinstock".AsWebsiteText(), x)); } result.AddError("Cart", sb.ToString()); } } return(result); }