public async Task Handle(ReserveCanceled msg, IMessageMetadata metadata = null)
        {
            using (var context = _contextFactory())
            {
                var skuStock = await context.SkuStocks.FindAsync(msg.SourceId);

                if (skuStock == null)
                {
                    throw new SkuStockEntryNotFoundException(msg.SourceId);
                }

                var reserve = await context.StockReserves.FindAsync(msg.SourceId, msg.ReserveId);

                if (reserve == null)
                {
                    throw new ReserveEntryNotFoundException(msg.SourceId);
                }

                var history = CreateHistory(skuStock, StockOperation.ReserveCanceled, reserve.Quantity);

                skuStock.AvailableQuantity += reserve.Quantity;
                skuStock.ReservedQuantity  -= reserve.Quantity;
                skuStock.LastModified       = msg.CreatedTime;
                skuStock.CustomersReservationsTotal--;

                FillNewQuantities(history, skuStock);

                context.StockReserves.Remove(reserve);
                context.StockHistory.Add(history);

                await context.SaveChangesAsync();
            }
        }
        public async Task Given_no_stock_When_reserve_cancel_projected_Then_error_occurs()
        {
            var stockId = Guid.NewGuid();

            var reserveCanceledEvent = new ReserveCanceled(stockId, Guid.NewGuid());

            await Assert.ThrowsAsync <SkuStockEntryNotFoundException>(() => ProjectionBuilder.Handle(reserveCanceledEvent));
        }
        public async Task Given_no_reserve_When_reserve_cancel_projected_Then_error_occurs()
        {
            var stockId = Guid.NewGuid();

            var stockCreatedEvent    = new SkuStockCreated(stockId, Guid.NewGuid(), 1, TimeSpan.FromDays(2));
            var reserveCanceledEvent = new ReserveCanceled(stockId, Guid.NewGuid());

            await ProjectionBuilder.Handle(stockCreatedEvent);

            await Assert.ThrowsAsync <ReserveEntryNotFoundException>(() => ProjectionBuilder.Handle(reserveCanceledEvent));
        }
        public SkuStock_reserve_canceled_tests()// Given_sku_created_and_stock_added_and_stock_reserved_messages_When_projected()
        {
            var stockId = Guid.NewGuid();

            _stockCreatedEvent    = new SkuStockCreated(stockId, Guid.NewGuid(), 1, TimeSpan.FromDays(2));
            _stockAddedEvent      = new StockAdded(stockId, 15, "test pack");
            _stockReservedEvent   = new StockReserved(stockId, Guid.NewGuid(), DateTime.Now.AddDays(1), 7);
            _reserveCanceledEvent = new ReserveCanceled(stockId, _stockReservedEvent.ReserveId);

            ProjectionBuilder.Handle(_stockCreatedEvent).Wait();
            ProjectionBuilder.Handle(_stockAddedEvent).Wait();
            ProjectionBuilder.Handle(_stockReservedEvent).Wait();
            ProjectionBuilder.Handle(_reserveCanceledEvent).Wait();
        }
        public async Task Given_sku_created_and_stock_added_and_stock_reserved_messages_When_projected_twice()
        {
            var stockId = Guid.NewGuid();

            var stockCreatedEvent    = new SkuStockCreated(stockId, Guid.NewGuid(), 1, TimeSpan.FromDays(2));
            var stockAddedEvent      = new StockAdded(stockId, 15, "test pack");
            var stockReservedEvent   = new StockReserved(stockId, Guid.NewGuid(), DateTime.Now.AddDays(1), 7);
            var reserveCanceledEvent = new ReserveCanceled(stockId, stockReservedEvent.ReserveId);

            await ProjectionBuilder.Handle(stockCreatedEvent);

            await ProjectionBuilder.Handle(stockAddedEvent);

            await ProjectionBuilder.Handle(stockReservedEvent);

            await ProjectionBuilder.Handle(reserveCanceledEvent);

            await ProjectionBuilder.Handle(reserveCanceledEvent)
            .ShouldThrow <ReserveEntryNotFoundException>();
        }