public async Task <PriceResult> CalculatePriceAsync(PriceRequestDTO request, Guid userId) { var products = request.Products.Where(g => g.Quantity > 0).ToArray(); if (!products.Any()) { return new PriceResult { Discount = 0, SummaryPrice = 0, Products = new System.Collections.Generic.List <PriceResult.CalculatedProductPrice>() } } ; _warehouseServiceClient.AddHeader(Constants.USERID_HEADER, userId.ToString()); var basePrices = await _warehouseServiceClient.ProductPriceAsync(products.Select(g => Guid.Parse(g.ProductId)).ToArray()); var discount = (100 - new Random().Next(0, 30)) / 100.0m; PriceResult result = new(); foreach (var prod in products) { var price = basePrices.First(k => k.Id == Guid.Parse(prod.ProductId)).BasePrice; result.SummaryPrice += price * prod.Quantity; } result.Discount = 100 - discount * 100; result.SummaryPrice *= discount; result.SummaryPrice = decimal.Round(result.SummaryPrice, 2); return(result); } }
public async Task <ActionResult <BucketResponseDTO> > UpdateBucket([FromRoute] Guid userId, BucketRequestDTO bucketRequest) { var bucket = _mapper.Map <Bucket>(bucketRequest); bucket.UserId = userId; // проверка наличия заказываемого количества товаров _warehouseServiceClient.AddHeader(Constants.USERID_HEADER, userId.ToString()); var allProducts = await _warehouseServiceClient.ProductInfoAsync(bucket.Items.Select(g => g.ProductId).ToArray()); foreach (var pr in bucket.Items) { var product = allProducts.FirstOrDefault(g => g.Id == pr.ProductId); if (product == null || pr.Quantity > product.RemainCount) { return(BadRequest()); } } var updateBucket = await _bucketRepository.UpdateBucketsAsync(bucket, userId); (decimal totalPrice, decimal discount)price = await _orderService.CalculateTotalPriceAsync(updateBucket, userId, true); var bucketsDTO = _mapper.Map <BucketResponseDTO>(updateBucket); bucketsDTO.SummaryPrice = price.totalPrice; bucketsDTO.Discount = price.discount; return(Ok(bucketsDTO)); }
public async Task <Order> CreateOrderAsync(Guid userId, CreateOrderDTO orderRequest) { // проверяем, не пришел ли второй раз тот же самый запрос var existOrder = _orderContext.Orders.FirstOrDefault(g => g.IdempotencyKey == orderRequest.IdempotencyKey); if (existOrder != null) { return(existOrder); } Order order = null; bool wasReserveProducts = false; try { var bucket = await _bucketRepository.GetBucketForUserAsync(userId); if (bucket == null || !bucket.Items.Any()) { return new Order { Status = OrderStatus.Error } } ; // 1. расчитываем стоимость (decimal totalPrice, decimal discount)price = await CalculateTotalPriceAsync(bucket, userId); // 2. сохраняем заказ в БД var orderItems = bucket.Items.Select(g => new OrderItem { ProductId = g.ProductId, Quantity = g.Quantity }).ToList(); using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { order = new Order { CreatedOnUtc = DateTime.UtcNow, DeliveryAddress = orderRequest.DeliveryAddress, Items = orderItems, Status = OrderStatus.Pending, UserId = userId, TotalPrice = price.totalPrice }; foreach (var item in orderItems) { item.Order = order; } _orderContext.Add(order); await _orderContext.SaveChangesAsync(); await _bucketRepository.ClearBucketAsync(userId); scope.Complete(); } // 3. резервируем на складе _warehouseServiceClient.AddHeader(Constants.USERID_HEADER, userId.ToString()); var reserve = await _warehouseServiceClient.ReserveAsync(new ReserveProductRequestDTO { OrderNumber = order.OrderNumber.ToString(), Products = order.Items.Select(g => new ReserveProductDTO { Id = g.ProductId, Count = g.Quantity }).ToList() }); wasReserveProducts = true; if (reserve.IsSuccess == false) { throw new Exception("Не удалось полностью зарезервировать товар"); } } catch (Exception ex) { if (wasReserveProducts) { try { await _warehouseServiceClient.CancelAsync(order.OrderNumber.ToString()); } catch (Exception inEx) { // логируем, что товар не сняли с резервирования } } try { if (order != null) { existOrder = _orderContext.Orders.FirstOrDefault(g => g.OrderNumber == order.OrderNumber); existOrder.Status = OrderStatus.Error; existOrder.ErrorDescription = ex.Message; await _orderContext.SaveChangesAsync(); } } catch (Exception inEx) { // логируем, что не удалось изменить статус } _metricReporter.RegisterFailedOrder(); } return(order); }