public void Percentage(decimal price, decimal percentage, decimal expected)
        {
            var product = new ProductEntity {
                Price = price
            };
            var record = new BasketRecordEntity {
                Count = 1, Product = product
            };
            var basket = new BasketEntity
            {
                Records = new[] { record }
            };
            var percentageDiscount = new DiscountEntity
            {
                Type          = DiscountEntityType.Percentage,
                Percentage    = percentage,
                TargetProduct = product
            };

            var dbPrice          = _sut.CalculatePrice(basket);
            var basketModel      = _sut.CalculatePriceWithDiscounts(basket, new[] { percentageDiscount });
            var basketModelPrice = _sut.CalculatePrice(basketModel);

            dbPrice.Should().Be(price);
            basketModelPrice.Should().Be(expected);
        }
Esempio n. 2
0
        public void Remove_ShouldRemoveItemToBasket_AndCallUpdate()
        {
            // Given
            var basketId     = Guid.NewGuid();
            var basketEntity = new BasketEntity {
                BasketId = basketId
            };
            var itemId     = Guid.NewGuid();
            var itemEntity = new ItemEntity {
                ItemId = itemId
            };

            basketEntity.Items.Add(itemEntity);
            _basketStore.Setup(x => x.Get(basketId)).Returns(basketEntity);
            _itemStore.Setup(x => x.Get(itemId)).Returns(itemEntity);
            var basketViewModel = new BasketViewModel {
                BasketId = basketId
            };

            _basketMapper.Setup(x => x.MapFrom(It.IsAny <BasketEntity>())).Returns(basketViewModel);

            // When
            var result = _basketService.Remove(basketId, itemId);

            // Then
            result.ShouldBe(basketViewModel);
            _basketStore.Verify(x => x.Update(It.Is <BasketEntity>(p => !p.Items.Any(y => y.ItemId == itemId))));
        }
Esempio n. 3
0
        public async Task <IResult> Delete(int basketId)
        {
            try
            {
                BasketEntity basket = await UnitOfWork.Basket.GetAsync(basket => basket.Id == basketId);

                if (basket != null)
                {
                    bool deleteResult = UnitOfWork.Basket.Delete(basket);
                    if (deleteResult)
                    {
                        return(new Result(ResultStatus.Success, $"{basket.Id} numaralı sepet silindi"));
                    }
                    else
                    {
                        return(new Result(ResultStatus.Error, "Silme işlemi gerçekleşmedi"));
                    }
                }
                return(new DataResult <BasketEntity>(ResultStatus.Error, "Böyle bir sepet bulunamadı", basket));
            }
            catch (Exception ex)
            {
                //_logger.Log(LogLevel.Error, ex, ex.Message);
                throw;
            }
        }
        public void BuyTwoGetOneFree(decimal price, int count, int expectedCount, decimal expectedPrice)
        {
            var product = new ProductEntity {
                Price = price
            };
            var record = new BasketRecordEntity {
                Count = count, Product = product
            };
            var basket = new BasketEntity
            {
                Records = new[] { record }
            };
            var percentageDiscount = new DiscountEntity
            {
                Type          = DiscountEntityType.BuyTwoGetOneForFree,
                TargetProduct = product,
                RewardProduct = product,
            };

            var dbPrice                 = _sut.CalculatePrice(basket);
            var basketModel             = _sut.CalculatePriceWithDiscounts(basket, new[] { percentageDiscount });
            var basketModelPrice        = _sut.CalculatePrice(basketModel);
            var basketModelProductCount = basketModel.Records[0].Count + basketModel.Records[0].FreeProducts.Count;

            dbPrice.Should().Be(price * record.Count);
            basketModelPrice.Should().Be(expectedPrice);
            basketModelProductCount.Should().Be(expectedCount);
        }
Esempio n. 5
0
        public void Update(BasketEntity basket)
        {
            var originalBasket = _baskets.SingleOrDefault(x => x.BasketId == basket.BasketId);

            _baskets.Remove(originalBasket);
            _baskets.Add(basket);
        }
        public async Task <ActionResult <Wrapper <BasketEntity> > > PostBasketEntity(BasketEntity basketEntity)
        {
            _context.Baskets.Add(basketEntity);
            await _context.SaveChangesAsync();

            return(new Wrapper <BasketEntity> {
                Data = basketEntity, Success = true
            });
        }
Esempio n. 7
0
        public async Task <BasketEntity> UpdateBasketAsync(BasketEntity basketEntity)
        {
            var created = await _database.StringSetAsync(basketEntity.Id, JsonSerializer.Serialize(basketEntity), TimeSpan.FromDays(30));

            if (!created)
            {
                return(null);
            }
            return(await GetBasketAsync(basketEntity.Id));
        }
Esempio n. 8
0
        public async Task <BasketEntity> InsertOrUpdate(BasketEntity basket)
        {
            basket.Id = basket.Id ?? Guid.NewGuid().ToString();

            var collection = database.GetCollection <BasketEntity>("commerce");

            var filter = Builders <BasketEntity> .Filter.Eq("_id", basket.Id);

            await collection.ReplaceOneAsync(filter, basket, new UpdateOptions { IsUpsert = true });

            return(basket);
        }
Esempio n. 9
0
        public Guid Create(Guid token)
        {
            var basket = new BasketEntity
            {
                BasketId = Guid.NewGuid(),
                Token    = token
            };

            _baskets.Add(basket);

            return(basket.BasketId);
        }
Esempio n. 10
0
        public BasketEntity BasketImporter(int id, List <ItemsEntity> itemsEntities,
                                           DateTime dateTime, CustomerEntity customer)
        {
            var basketOfCustomer = new BasketEntity();

            basketOfCustomer.Id             = id;
            basketOfCustomer.ItemsList      = itemsEntities;
            basketOfCustomer.EnterDateTime  = dateTime;
            basketOfCustomer.CustomerEntity = customer;

            // حذف اقلام مورد نیاز مشتری از فروشگاه پس از آنکه خریداری انجام گرفت
            DelItemFrmShop(itemsEntities);

            return(basketOfCustomer);
        }
Esempio n. 11
0
        public async Task <IResult> Update(BasketDto basketUpdateDto)
        {
            try
            {
                BasketEntity basket = Mapper.Map <BasketEntity>(basketUpdateDto);
                await UnitOfWork.Basket.UpdateAsync(basket);

                await UnitOfWork.SaveAsync();

                BasketDto result = Mapper.Map <BasketEntity, BasketDto>(basket);
                return(new Result(ResultStatus.Success, $"{basket.Id} li sepet güncellendi"));
            }
            catch (Exception ex)
            {
                //_logger.Log(LogLevel.Error, ex, ex.Message);
                throw;
            }
        }
Esempio n. 12
0
        public async Task <IResult> Insert(BasketDto basketAddDto)
        {
            try
            {
                BasketEntity basket = Mapper.Map <BasketEntity>(basketAddDto);
                await UnitOfWork.Basket.AddAsync(basket);

                await UnitOfWork.SaveAsync();

                BasketDto result = Mapper.Map <BasketEntity, BasketDto>(basket);
                return(new Result(ResultStatus.Success, $"{result.Id} eklendi"));
            }
            catch (Exception ex)
            {
                //_logger.Log(LogLevel.Error, ex, ex.Message);
                throw;
            }
        }
        public async Task <BasketEntity> UpdateBasketAsync(BasketEntity basketEntity,
                                                           string correlationToken,
                                                           TelemetryClient telemetryClient)
        {
            // Telemetry variables
            var success     = false;
            var startTime   = DateTime.UtcNow;
            var timer       = System.Diagnostics.Stopwatch.StartNew();
            var returnValue = "Not Found";

            try
            {
                var created =
                    await _database.StringSetAsync(basketEntity.BasketId, JsonConvert.SerializeObject(basketEntity));

                // _database.SetAdd()

                if (!created)
                {
                    _logger.LogInformation("Redis cache could not persist an item.");
                    return(null);
                }
                else
                {
                    success     = true;
                    returnValue = basketEntity.BasketId;
                    _logger.LogInformation("Redis cache persisted item succesfully.");
                }
            }
            catch (Exception ex)
            {
                telemetryClient.TrackException(ex);
                _logger.LogError(ex.ToString());
                throw;
            }
            finally
            {
                telemetryClient.TrackDependency("RedisCache", "UpdateBasket", returnValue, startTime, timer.Elapsed, success);
            }

            return(await  GetBasketAsync(returnValue));

            //return null;
        }
Esempio n. 14
0
        public async Task <IDataResult <BasketDto> > Get(int basketId)
        {
            try
            {
                BasketEntity basketEntities = await UnitOfWork.Basket.GetAsync(basket => basket.Id == basketId);

                BasketDto basketDto = Mapper.Map <BasketEntity, BasketDto>(basketEntities);
                if (basketDto != null)
                {
                    return(new DataResult <BasketDto>(ResultStatus.Success, basketDto));
                }
                return(new DataResult <BasketDto>(ResultStatus.Error, "Böyle bir sepet bulunamadı", data: null));
            }
            catch (Exception ex)
            {
                //_logger.Log(LogLevel.Error, ex, ex.Message);
                throw;
            }
        }
Esempio n. 15
0
        public BasketViewModel MapFrom(BasketEntity basketEntity)
        {
            var itemViewModels = new List <ItemViewModel>();
            var items          = basketEntity.Items.GroupBy(x => x.ItemId);

            foreach (var item in items)
            {
                var itemViewModel = _itemMapper.MapFrom(item.First());
                itemViewModel.Quantity = item.Count();
                itemViewModels.Add(itemViewModel);
            }

            return(new BasketViewModel
            {
                BasketId = basketEntity.BasketId,
                Token = basketEntity.Token,
                Items = itemViewModels,
                Total = basketEntity.Items.Sum(x => x.Cost)
            });
        }
Esempio n. 16
0
        public void Get_ShouldFetchBasketDetailsFromBasketStore()
        {
            // Given
            var basketId     = Guid.NewGuid();
            var basketEntity = new BasketEntity {
                BasketId = basketId
            };

            _basketStore.Setup(x => x.Get(basketId)).Returns(basketEntity);
            var basketViewModel = new BasketViewModel {
                BasketId = basketId
            };

            _basketMapper.Setup(x => x.MapFrom(basketEntity)).Returns(basketViewModel);

            // When
            var result = _basketService.Get(basketId);

            // Then
            result.ShouldBe(basketViewModel);
        }
        public void ShouldMapEntityToModel()
        {
            AutoMapperConfiguration.Configure();

            const string Id = "My Id";

            var entity = new BasketEntity
            {
                Id    = Id,
                Items = new[] { new ProductEntity {
                                    Id = 42, Name = "Name", Cost = new MoneyEntity(4200, SE.ISOCurrencySymbol)
                                } }
            };

            var model = AutoMapperConfiguration.Mapper.Map <Basket>(entity);

            Assert.Equal(Id, model.Id);
            Assert.Single(model.Products);
            Assert.Equal(1, model.Count);
            Assert.Equal(new Money(42.0, SE), model.Total);
        }
Esempio n. 18
0
 public void ShowResult(BasketEntity basket)
 {
     Console.ForegroundColor = ConsoleColor.Red;
     Console.WriteLine($"================= Basket Id is: {basket.Id} =================\n");
     Console.ForegroundColor = ConsoleColor.White;
     Console.WriteLine($"Customer Id: {basket.CustomerEntity.Id}");
     Console.WriteLine($"FullName: {basket.CustomerEntity.FullName}");
     Console.WriteLine($"Gender: {basket.CustomerEntity.Gender}");
     Console.WriteLine($"Date Entrance: {basket.EnterDateTime}");
     foreach (var item in basket.ItemsList)
     {
         Console.WriteLine($"Name item is: {item.Stuff} and Quntity is: {item.Qnt}");
     }
     Console.WriteLine("\n");
     Console.ForegroundColor = ConsoleColor.DarkBlue;
     Console.WriteLine("########## Shop remaind ##########");
     foreach (var item in Repository.UpdateShopItems)
     {
         Console.WriteLine($"Name item is: {item.Stuff} and Quntity is: {item.Qnt}");
     }
     Console.ForegroundColor = default;
     Console.WriteLine("\n");
 }
Esempio n. 19
0
        public BasketModel CalculatePriceWithDiscounts(BasketEntity basket, IEnumerable <DiscountEntity> discounts)
        {
            var basketModel = new BasketModel();

            foreach (var discount in discounts)
            {
                var handler = _handlers.SingleOrDefault(x => x.CanHandle(discount));
                foreach (var record in basket.Records)
                {
                    if (handler != null && handler.IsApplicable(record, discount))
                    {
                        basketModel.Records.Add(handler.Apply(record, discount));
                    }
                    else
                    {
                        basketModel.Records.Add(new BasketRecordModel(record.Count,
                                                                      new ProductModel(record.Product.Price)));
                    }
                }
            }

            return(basketModel);
        }
Esempio n. 20
0
        public async Task ShouldAddProductToBasket()
        {
            const string BasketId = "My basket id";
            var          entity   = new BasketEntity
            {
                Id = BasketId
            };

            var product = new Product(42, "What name?", new Money(13.76, SE));

            var repositoryMock = new Mock <IRepository>(MockBehavior.Strict);

            repositoryMock
            .Setup(repository => repository.GetById(BasketId))
            .ReturnsAsync(entity);

            repositoryMock
            .Setup(repository => repository.InsertOrUpdate(It.IsAny <BasketEntity>()))
            .ReturnsAsync(entity);

            var productServiceMock = new Mock <IProductService>(MockBehavior.Strict);

            productServiceMock.Setup(productService => productService.GetById(42)).ReturnsAsync(product);

            var service = new BasketService(productServiceMock.Object, repositoryMock.Object);

            await service.AddProductToBasket(BasketId, 42);

            repositoryMock.VerifyAll();
            repositoryMock.Verify(repository => repository.InsertOrUpdate(
                                      It.Is <BasketEntity>(item =>
                                                           item.Id == BasketId &&
                                                           item.Items.Single().Cost.Units == product.Cost.Units &&
                                                           item.Items.Single().Id == 42)), Times.Once);

            productServiceMock.VerifyAll();
        }
Esempio n. 21
0
        public void Clear_ShouldRemoveItemsFromBasket_AndCallUpdate()
        {
            // Given
            var basketId     = Guid.NewGuid();
            var basketEntity = new BasketEntity {
                BasketId = basketId, Items = new List <ItemEntity> {
                    new ItemEntity(), new ItemEntity()
                }
            };

            _basketStore.Setup(x => x.Get(basketId)).Returns(basketEntity);
            var basketViewModel = new BasketViewModel {
                BasketId = basketId
            };

            _basketMapper.Setup(x => x.MapFrom(basketEntity)).Returns(basketViewModel);

            // When
            var result = _basketService.Clear(basketId);

            // Then
            result.ShouldBe(basketViewModel);
            _basketStore.Verify(x => x.Update(It.Is <BasketEntity>(p => p.Items.Count == 0)));
        }
Esempio n. 22
0
        public async Task ShouldCreateEmptyBasket()
        {
            const string BasketId = "My basket id";
            var          entity   = new BasketEntity {
                Id = BasketId
            };

            var repositoryMock = new Mock <IRepository>(MockBehavior.Strict);

            repositoryMock
            .Setup(repository => repository.InsertOrUpdate(It.IsAny <BasketEntity>()))
            .ReturnsAsync(entity);

            var productServiceMock = new Mock <IProductService>(MockBehavior.Strict);

            var service = new BasketService(productServiceMock.Object, repositoryMock.Object);

            var created = await service.CreateBasket();

            Assert.Equal(0, created.Count);
            Assert.Equal(BasketId, created.Id);

            repositoryMock.VerifyAll();
        }
Esempio n. 23
0
 public decimal CalculatePrice(BasketEntity basket)
 {
     return(basket.Records.Sum(x => x.Count * x.Product.Price));
 }
Esempio n. 24
0
        /// <summary>
        ///     Add single line item to shopping basket
        /// </summary>
        /// <param name="productId">Id of productEntity to add</param>
        /// <param name="correlationToken">Tracks request - can be any value</param>
        /// <param name="basketId">Id of shopping basket</param>
        /// <returns>BasketItemEntity</returns>
        public async Task <BasketEntity> AddItemToBasket(int productId, string correlationToken,
                                                         string basketId)
        {
            //* Materialized View Pattern
            //* Fetch product entity data from a read-only store contained in shopping basket service.
            //* ProductEntity ID is row key in underlying Azure table.
            //* Returns a ProductTableEntity class
            var productTableEntity = await _productRepository.GetItem(ProductPartitionKey, productId.ToString(), correlationToken);

            // Fallback logic
            if (productTableEntity == null)
            {
                // Fallback:
                // If product not available from local read store, fetch it from catalog service by
                // making direct HTTP call to Catalog Service.
                var product = await _restClient.GetAsync <ProductEntity>(ServiceEnum.Catalog, $"api/Catalog/Music/{productId}", correlationToken);

                if (product == null)
                {
                    throw new Exception(
                              $"Cannot add item to shopping basket: ProductEntity #{productId} does not exist for Request {correlationToken}.  Have you created the ProductEntity Read Model for the Shopping BasketEntity microservice?");
                }

                // Transform product into an entity class for table storage
                productTableEntity = new ProductTableEntity
                {
                    // parition key is constant
                    PartitionKey = ProductPartitionKey,
                    // row key is productId
                    RowKey = product.Data.Id.ToString(),

                    Title      = product.Data.Title,
                    Id         = product.Data.Id,
                    GenreName  = product.Data.GenreName,
                    ArtistName = product.Data.ArtistName,
                    Price      = product.Data.Price.ToString()
                };

                // Add product entity tolocal read store, implementing a cache-aside pattern
                await _productRepository.Insert(productTableEntity, correlationToken);

                _logger.LogInformation(
                    $"Added productEntity information for item {productId} for Request {correlationToken} to the read model.");
            }

            BasketEntity basket = null;

            // Does basketID exist?
            if (basketId == "-1")
            {
                basketId = SnowflakeIdGenerator.GenerateId(SnowflakeEnum.Basket);
            }
            else
            {
                basket = await _distributedCacheRepository.GetBasketAsync(basketId, correlationToken, _telemetryClient);
            }

            // Get basket from cache
            if (basket == null)
            {
                // BasketEntity is null, add new single item to it
                basket = new BasketEntity
                {
                    BuyerId          = "2",
                    BasketId         = basketId,
                    CorrelationToken = correlationToken,
                    Items            =
                    {
                        new BasketItemEntity
                        {
                            CorrelationToken = correlationToken,
                            //DateCreated = DateTime.Now,
                            Title     = productTableEntity.Title,
                            UnitPrice = productTableEntity.Price.ToString(),
                            Artist    = productTableEntity.ArtistName,
                            Genre     = productTableEntity.GenreName,
                            Quantity  = 1,
                            ProductId = productId,
                        }
                    }
                };

                basket = await _distributedCacheRepository.UpdateBasketAsync(basket, correlationToken, _telemetryClient);

                _logger.LogInformation($"Created new shopping basket {basketId} and added productEntity {productTableEntity.Title} for Request {correlationToken} ");
            }
            else
            {
                // BasketEntity is not null
                // Determine if the same productEntity has already been added to the basket
                var itemInBasket = basket.Items.FirstOrDefault(x => x.ProductId == Int32.Parse(productTableEntity.RowKey));

                if (itemInBasket == null)
                {
                    // ProductEntity does not exist in basket, add it
                    basket.Items.Add(new BasketItemEntity()
                    {
                        CorrelationToken = correlationToken,
                        //DateCreated = DateTime.Now,
                        Title     = productTableEntity.Title,
                        UnitPrice = productTableEntity.Price.ToString(),
                        Artist    = productTableEntity.ArtistName,
                        Genre     = productTableEntity.GenreName,
                        Quantity  = 1,
                        ProductId = Int32.Parse(productTableEntity.RowKey)
                    });

                    _logger.LogInformation($"Added productEntity Id {productId} to shopping basket {basketId} for request {correlationToken}");
                }
                else
                {
                    // Idempotency write-check
                    // Ensure that update with same correlation token does not already exist.
                    // This could happen if we've already committed the write, but have gotten caught-up in retry logic.
                    if (itemInBasket.CorrelationToken != null && itemInBasket.CorrelationToken == correlationToken)
                    {
                        _logger.LogWarning($"ProductEntity Id {productId} already added to shopping basket {basketId} for Request {correlationToken}");
                        return(basket);
                    }

                    // ProductEntity already exists in basket. Increment its count.
                    basket.Items.FirstOrDefault(x => x.ProductId == Int32.Parse(productTableEntity.RowKey)).Quantity++;

                    _logger.LogInformation($"Added productEntity Id {productId} to existing shopping basket {basketId} for request {correlationToken}");
                }

                basket = await _distributedCacheRepository.UpdateBasketAsync(basket, correlationToken, _telemetryClient);
            }

            return(basket);
        }