Example #1
0
        public async Task HandleAsync(AddReservationsCommand command, CancellationToken cancellationToken)
        {
            using (var context = dbContextFactory.CreateDbContext())
            {
                var productIds = command.Items.Select(i => i.ProductId).ToList();

                var productLookup = await GetProductLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false);

                requestValidator.ValidateAndThrow(command, productLookup);

                // This is for idempotence. We check only the TransactionId because we assume that if one item in a transaction is reserved then so are the others.
                var alreadyReserved = await context.ProductReservations.AnyAsync(r => r.TransactionId == command.TransactionId, cancellationToken).ConfigureAwait(false);

                if (alreadyReserved)
                {
                    return;
                }

                foreach (var addedReservation in command.Items)
                {
                    context.ProductReservations.Add(new ProductReservation
                    {
                        ProductId     = addedReservation.ProductId,
                        Quantity      = addedReservation.Quantity,
                        TransactionId = command.TransactionId
                    });
                }

                await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }
        }
        public async Task HandleAsync(RemoveStocksCommand command, CancellationToken cancellationToken)
        {
            using (var context = dbContextFactory.CreateDbContext())
            {
                var productIds = command.Items.Select(i => i.ProductId).ToList();

                var productLookup = await GetProductLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false);

                var availableCountLookup = await GetAvailabileCountLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false);

                requestValidator.ValidateAndThrow(command, productLookup, availableCountLookup);

                // This is for idempotence. We check only the TransactionId because we assume that if stocks for one product in a transaction is removed then so are the others.
                var stocksAlreadyRemoved = await context.ProductStockRemovedEvents.AnyAsync(evt => evt.TransactionId == command.TransactionId, cancellationToken).ConfigureAwait(false);

                if (stocksAlreadyRemoved)
                {
                    return;
                }

                foreach (var removedStock in command.Items)
                {
                    context.ProductStockRemovedEvents.Add(new ProductStockRemovedEvent
                    {
                        ProductId     = removedStock.ProductId,
                        Quantity      = removedStock.Quantity,
                        TransactionId = command.TransactionId
                    });
                }

                await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }
        }
        public async Task HandleAsync(TakeoutItemsCommand command, CancellationToken cancellationToken)
        {
            using (var context = dbContextFactory.CreateDbContext())
            {
                var productIds = command.Items.Select(i => i.ProductId).ToList();

                var productLookup = await GetProductLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false);

                var reservationLookup = await GetReservationLookupAsync(context, command.TransactionId, cancellationToken).ConfigureAwait(false);

                var availableCountLookup = await GetAvailabileCountLookupAsync(context, productIds, cancellationToken).ConfigureAwait(false);

                requestValidator.ValidateAndThrow(command, productLookup, reservationLookup, availableCountLookup);

                // This is for idempotence. We check only the TransactionId because we assume that if one item in a transaction is taken out then so are the others.
                var itemsAlreadyTakenOut = await context.ProductTakenOutEvents.AnyAsync(evt => evt.TransactionId == command.TransactionId, cancellationToken).ConfigureAwait(false);

                if (itemsAlreadyTakenOut)
                {
                    return;
                }

                foreach (var takenOutItem in command.Items)
                {
                    context.ProductTakenOutEvents.Add(new ProductTakenOutEvent
                    {
                        ProductId     = takenOutItem.ProductId,
                        Quantity      = takenOutItem.Quantity,
                        TransactionId = command.TransactionId
                    });
                }

                await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }
        }
Example #4
0
        public async Task <GetProductByIdResponse> HandleAsync(GetProductByIdRequest request, CancellationToken cancellationToken)
        {
            using (var context = dbContextFactory.CreateDbContext())
            {
                var product = await context.Products.FindAsync(new[] { request.ProductId }, cancellationToken).ConfigureAwait(false);

                if (product == null)
                {
                    return(null);
                }

                return(new GetProductByIdResponse
                {
                    Name = product.Name,
                    ProductId = product.Id,
                    PointsCost = product.PointsCost
                });
            }
        }
        public async Task HandleAsync(CancelReservationsCommand command, CancellationToken cancellationToken)
        {
            using (var context = dbContextFactory.CreateDbContext())
            {
                requestValidator.ValidateAndThrow(command);

                var productReservations = await context
                                          .ProductReservations
                                          .Where(evt => evt.TransactionId == command.TransactionId)
                                          .ToListAsync(cancellationToken)
                                          .ConfigureAwait(false);

                if (productReservations.Count == 0)
                {
                    return;
                }

                context.ProductReservations.RemoveRange(productReservations);

                await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }
        }
Example #6
0
        public async Task HandleAsync(BringbackItemsCommand command, CancellationToken cancellationToken)
        {
            using (var context = dbContextFactory.CreateDbContext())
            {
                requestValidator.ValidateAndThrow(command);

                // This is for idempotence. We check only the TransactionId because we assume that if one item in a transaction is brought back then so are the others.
                var itemsAlreadyBroughtBack = await context.ProductBroughtBackEvents.AnyAsync(evt => evt.TransactionId == command.TransactionId, cancellationToken).ConfigureAwait(false);

                if (itemsAlreadyBroughtBack)
                {
                    return;
                }

                var correspondingTakeoutEvents = await context
                                                 .ProductTakenOutEvents
                                                 .AsNoTracking()
                                                 .Where(evt => evt.TransactionId == command.TransactionId)
                                                 .ToListAsync(cancellationToken)
                                                 .ConfigureAwait(false);

                if (correspondingTakeoutEvents.Count == 0)
                {
                    return;
                }

                foreach (var takeoutEvent in correspondingTakeoutEvents)
                {
                    context.ProductBroughtBackEvents.Add(new ProductBroughtBackEvent
                    {
                        ProductId     = takeoutEvent.ProductId,
                        Quantity      = takeoutEvent.Quantity,
                        TransactionId = command.TransactionId
                    });
                }

                await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }
        }
        public async Task <CreateProductResponse> HandleAsync(CreateProductCommand command, CancellationToken cancellationToken)
        {
            requestValidator.ValidateAndThrow(command);

            using (var context = dbContextFactory.CreateDbContext())
            {
                var product = new Product
                {
                    Name       = command.Name,
                    PointsCost = command.PointsCost
                };

                context.Products.Add(product);

                await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);

                return(new CreateProductResponse
                {
                    PointsCost = product.PointsCost,
                    ProductId = product.Id,
                    Name = product.Name
                });
            }
        }