예제 #1
0
        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);
        }
    }
예제 #2
0
        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));
        }
예제 #3
0
        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);
        }