public async Task <InsuranceCostDto> CalculateOrderInsurance([FromBody] CalculateOrderInsuranceRequest calculateOrderInsuranceRequest) { var insuranceCost = await _insuranceCalculatorService.CalculateOrderInsuranceAsync(calculateOrderInsuranceRequest); return(new InsuranceCostDto(insuranceCost)); }
public async Task <decimal> CalculateOrderInsuranceAsync(CalculateOrderInsuranceRequest request) { var productDataTasks = request .Items .Select(item => item.ProductId) .Distinct() .Select(productId => _productApiClient.GetProductByIdAsync(productId)) .ToList(); await Task.WhenAll(productDataTasks); var productTypeTasks = productDataTasks .Select(task => task.Result.ProductTypeId) .Distinct() .Select(productTypeId => _productApiClient.GetProductTypeByIdAsync(productTypeId)) .ToList(); await Task.WhenAll(productTypeTasks); var rangeRules = await _dbContext .InsuranceRangeRules .AsNoTracking() .ToListAsync(); var productTypeRules = await _dbContext .InsuranceProductTypeRules .AsNoTracking() .ToListAsync(); var productDataDictionary = productDataTasks .ToDictionary(task => task.Result.Id, task => task.Result); var productTypeDictionary = productTypeTasks .ToDictionary(task => task.Result.Id, task => task.Result); var insuranceCost = request .Items .Sum(CalculateOrderItemInsurance); return(insuranceCost); decimal CalculateOrderItemInsurance(OrderItemDto item) { var product = productDataDictionary[item.ProductId]; var productType = productTypeDictionary[product.ProductTypeId]; if (!productType.CanBeInsured) { return(0); } var singleItemInsuranceCost = 0M; var insuranceRangeRule = rangeRules .FirstOrDefault(rule => rule.InclusiveMinSalePrice <= product.SalesPrice && rule.ExclusiveMaxSalePrice > product.SalesPrice); var insuranceProductTypeOnProductRule = productTypeRules .SingleOrDefault(rule => rule.ProductTypeId == productType.Id && rule.Type == InsuranceProductTypeRuleType.AppliesToProduct); var insuranceProductTypeOnOrderRule = productTypeRules .SingleOrDefault(rule => rule.ProductTypeId == productType.Id && rule.Type == InsuranceProductTypeRuleType.AppliesToOrder); if (insuranceRangeRule != null) { singleItemInsuranceCost += insuranceRangeRule.InsuranceCost; } if (insuranceProductTypeOnProductRule != null) { singleItemInsuranceCost += insuranceProductTypeOnProductRule.InsuranceCost; } var totalInsuranceCost = singleItemInsuranceCost * item.Quantity; if (insuranceProductTypeOnOrderRule != null) { totalInsuranceCost += insuranceProductTypeOnOrderRule.InsuranceCost; } return(totalInsuranceCost); } }