public async Task <IEnumerable <DbPrice> > Recalculation(int productId, int groupId, int pbandId, int setId, int unitId, bool storePrices, DateTime?arrivedTime) { List <DbPrice> prices = new List <DbPrice>(); DateTime dt = DateTime.UtcNow; if (arrivedTime.HasValue) { dt = arrivedTime.Value; } var lastRecalculationTime = await _pricingRepo.GetLastMsmqStartTime(productId); var canRecalculate = CanRecalculate(lastRecalculationTime, dt); //validate - is it last recalculation more actual that current request date if (!canRecalculate) { var logId = await _pricingRepo.CreateMsmqLog("Dish Pricing Calculation Skipped", productId, groupId, pbandId, setId, unitId, dt); await _pricingRepo.UpdateMsmqLog(dt, logId, true); } else { var productsAndParts = await _pricingRepo.GetProductsAndParts(productId); var products = productsAndParts.Item1; var parts = productsAndParts.Item2; bool restictBySupplier = await _pricingRepo.IsIngredientAccess(); IEnumerable <IngredientAlternate> alternates = new List <IngredientAlternate>(); if (restictBySupplier) { alternates = await _pricingRepo.GetIngredientAlternates(null); } ProductForest pf = new ProductForest(products.ToList(), parts.ToList(), alternates.ToList()); pf.BuildForest(); var groupPrices = await _pricingRepo.GetGroupProductPricesByProduct(productId); Dictionary <int, ProductForest.CalculatedPrices> newProductPrices = pf.CalculatePrice(groupPrices.ToList(), restictBySupplier); var logId = await _pricingRepo.CreateMsmqLog("Dish Pricing Calculation", productId, groupId, pbandId, setId, unitId, dt); bool isSuccess = true; foreach (var group in newProductPrices) { //delete old prices which are no longer valid var requiredPrices = groupPrices.Where(x => (x.GroupId.HasValue && x.GroupId == group.Key) || (group.Key == 0 && !x.GroupId.HasValue)); List <int> itemsToDelete = new List <int>(); foreach (var price in requiredPrices) { if (!group.Value.Prices.ContainsKey((price.ProductId))) { itemsToDelete.Add(price.ProductId); } } int?calculatedGroupId = null; if (group.Key > 0) { calculatedGroupId = group.Key; } //delete items for which we require prices but prices was not generated if (itemsToDelete.Any()) { await _pricingRepo.ClearPrices(itemsToDelete, calculatedGroupId); var msgDelete = $"Delete prices for group {group.Key} total prices {itemsToDelete.Count}"; DebugLog(msgDelete); } var msgStart = $"Start saving group {group.Key} total prices {group.Value.Prices.Count} at {DateTime.UtcNow}"; DebugLog(msgStart); bool saveResult = _pricingRepo.UpdatePrices(group.Value.Prices, calculatedGroupId, logId, dt); ErrorLog(group.Value.Errors.ToString()); var msgEnd = $"End saving group {group.Key} total prices {group.Value.Prices.Count} at {DateTime.UtcNow}"; DebugLog(msgEnd); if (!saveResult) { isSuccess = false; } } await _pricingRepo.UpdateMsmqLog(DateTime.UtcNow, logId, isSuccess); foreach (var group in newProductPrices) { foreach (var productPrice in group.Value.Prices) { prices.Add(new DbPrice() { GroupId = group.Key, ProductId = productPrice.Key, Price = productPrice.Value }); } } } return(prices); }