public async Task <Coupon> GetCoupon(Guid couponId)
        {
            var id = Activity.Current.TraceId.ToString();

            try
            {
                GetCouponByIdRequest getCouponByIdRequest = new GetCouponByIdRequest {
                    CouponId = couponId.ToString()
                };

                GetCouponByIdResponse getCouponByIdResponse = await discountsService.GetCouponAsync(getCouponByIdRequest);

                var coupon = new Coupon
                {
                    Code        = getCouponByIdResponse.Coupon.Code,
                    Amount      = getCouponByIdResponse.Coupon.Amount,
                    AlreadyUsed = getCouponByIdResponse.Coupon.AlreadyUsed,
                    CouponId    = Guid.Parse(getCouponByIdResponse.Coupon.CouponId)
                };

                return(coupon);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
        public async Task <IActionResult> ApplyCouponToBasket(Guid basketId, Coupon coupon)
        {
            var basket = await basketRepository.GetBasketById(basketId);

            if (basket == null)
            {
                return(BadRequest());
            }

            basket.CouponId = coupon.CouponId;
            await basketRepository.SaveChanges();

            return(Accepted());
        }
        public async Task <IActionResult> CheckoutBasketAsync([FromBody] BasketCheckout basketCheckout)
        {
            try
            {
                //based on basket checkout, fetch the basket lines from repo
                var basket = await basketRepository.GetBasketById(basketCheckout.BasketId);

                if (basket == null)
                {
                    return(BadRequest());
                }

                BasketCheckoutMessage basketCheckoutMessage = mapper.Map <BasketCheckoutMessage>(basketCheckout);
                basketCheckoutMessage.BasketLines = new List <BasketLineMessage>();
                int total = 0;

                foreach (var b in basket.BasketLines)
                {
                    var basketLineMessage = new BasketLineMessage
                    {
                        BasketLineId = b.BasketLineId,
                        Price        = b.Price,
                        TicketAmount = b.TicketAmount
                    };

                    total += b.Price * b.TicketAmount;

                    basketCheckoutMessage.BasketLines.Add(basketLineMessage);
                }

                //apply discount by talking to the discount service
                Coupon coupon = null;

                //if (basket.CouponId.HasValue)
                //    coupon = await discountService.GetCoupon(basket.CouponId.Value);

                if (basket.CouponId.HasValue)
                {
                    coupon = await discountService.GetCouponWithError(basket.CouponId.Value);
                }

                //var channel = GrpcChannel.ForAddress("https://localhost:5007");

                //DiscountService discountService = new DiscountService(new Discounts.DiscountsClient(channel));
                //if (basket.CouponId.HasValue)
                //    coupon = await discountService.GetCoupon(basket.CouponId.Value);

                if (coupon != null)
                {
                    basketCheckoutMessage.BasketTotal = total - coupon.Amount;
                }
                else
                {
                    basketCheckoutMessage.BasketTotal = total;
                }

                try
                {
                    await messageBus.PublishMessage(basketCheckoutMessage, "checkoutmessage");
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }

                await basketRepository.ClearBasket(basketCheckout.BasketId);

                return(Accepted(basketCheckoutMessage));
            }
            catch (BrokenCircuitException ex)
            {
                string message = ex.Message;
                return(StatusCode(StatusCodes.Status500InternalServerError, ex.StackTrace));
            }
            catch (Exception e)
            {
                return(StatusCode(StatusCodes.Status500InternalServerError, e.StackTrace));
            }
        }
        public async Task <IActionResult> CheckoutBasketAsync([FromBody] BasketCheckout basketCheckout)
        {
            using var scope = logger.BeginScope("Checking out basket {BasketId}", basketCheckout.BasketId);

            try
            {
                //based on basket checkout, fetch the basket lines from repo
                var basket = await basketRepository.GetBasketById(basketCheckout.BasketId);

                if (basket == null)
                {
                    logger.LogWarning("Basket was not found");
                    return(BadRequest());
                }

                logger.LogDebug("Loaded basket");

                BasketCheckoutMessage basketCheckoutMessage = mapper.Map <BasketCheckoutMessage>(basketCheckout);
                basketCheckoutMessage.BasketLines = new List <BasketLineMessage>();
                int total = 0;

                foreach (var b in basket.BasketLines)
                {
                    var basketLineMessage = new BasketLineMessage
                    {
                        BasketLineId = b.BasketLineId,
                        Price        = b.Price,
                        TicketAmount = b.TicketAmount
                    };

                    total += b.Price * b.TicketAmount;

                    basketCheckoutMessage.BasketLines.Add(basketLineMessage);
                }

                //apply discount by talking to the discount service
                Coupon coupon = null;

                var channel = GrpcChannel.ForAddress("https://localhost:5007");

                DiscountService discountService = new DiscountService(new Discounts.DiscountsClient(channel));
                if (basket.CouponId.HasValue)
                {
                    coupon = await discountService.GetCoupon(basket.CouponId.Value);
                }

                if (coupon != null)
                {
                    logger.LogDebug("Applying discount {DiscountAmount} from {CouponId}", coupon.Amount, basket.CouponId.Value);
                    basketCheckoutMessage.BasketTotal = total - coupon.Amount;
                }
                else
                {
                    logger.LogDebug("No discount to apply");
                    basketCheckoutMessage.BasketTotal = total;
                }

                try
                {
                    await messageBus.PublishMessage(basketCheckoutMessage, "checkoutmessage",
                                                    Activity.Current.TraceId.ToString());

                    logger.LogDebug("Published checkout message");
                }
                catch (Exception e)
                {
                    logger.LogError(e, "Unable to publish checkout message");
                    throw;
                }

                await basketRepository.ClearBasket(basketCheckout.BasketId);

                return(Accepted(basketCheckoutMessage));
            }
            catch (Exception e)
            {
                logger.LogError(e, "An exception occurred when checking out the basket");

                return(StatusCode(StatusCodes.Status500InternalServerError, e.StackTrace));
            }
        }