Example #1
0
        public async Task <Reservation> BookCarReservationAsync(BookCarReservationParameters parameters)
        {
            var clientTask = clientRep.GetAsync(parameters.ClientId);
            var carTask    = carRep.GetAsync(parameters.CarId);
            var client     = await clientTask;
            var car        = await carTask;

            await ValidateAsync(parameters, car, client);

            var reservation = new Reservation()
            {
                Car            = car,
                Client         = client,
                PickUpDateTime = parameters.PickUpDateTime,
                ReturnDateTime = parameters.ReturnDateTime,
                State          = ReservationState.Booked
            };

            reservation.ClientAccount = new ClientAccount()
            {
                CancellationFeeValueAtBookingMoment = car.Type.CancellationRateFee,
                RentalRateFeeValueAtBookingMoment   = car.Type.RentalRateFee,
                DepositFeePaid = CalculateDepositFeeToPay(reservation)
            };

            reservationRep.Insert(reservation);

            await uow.CompleteAsync();

            return(reservation);
        }
        [InlineData(200, 100, 1, 10, true, ErrorCode.PendingReservationExists)]           //exists pending reservation
        public async Task BookCarReservationAsync_InvalidReservation_ThrowsCustomException(long carId, long clientId, int pickupHours, int returnHours, bool hasReservation, ErrorCode errorCode)
        {
            //Arrange
            var rentalRateFee       = 10;
            var depositFee          = 0.5m;
            var cancellationRateFee = 5;

            var mockedReservationRepository = hasReservation ? GetReservationRepositoryWithPendingReservation() : GetReservationRepositoryWithoutReservation();
            var mockedCarRepository         = GetCarRepositoryWithCar(200, rentalRateFee, depositFee, cancellationRateFee);
            var mockedClientRepository      = GetClientRepositoryWithClient(100);
            var bl = new BLReservation(mockedReservationRepository, mockedCarRepository, mockedClientRepository, mockedUnitOfWork);

            var pickupDateTime = DateTime.Now.AddHours(pickupHours);
            var returnDateTime = DateTime.Now.AddHours(returnHours);
            var parameters     = new BookCarReservationParameters()
            {
                CarId          = carId,
                ClientId       = clientId,
                PickUpDateTime = pickupDateTime,
                ReturnDateTime = returnDateTime
            };

            //Act
            async Task act() => await bl.BookCarReservationAsync(parameters);

            //Assert
            var exception = await Assert.ThrowsAsync <CustomException>(act);

            Assert.Equal(errorCode, exception.code);
        }
        private async Task ValidateAsync(BookCarReservationParameters parameters, Car car, Client client)
        {
            if (car == null)
            {
                throw new CustomException($"Unknown Car - Id {parameters.CarId}", ErrorCode.UnknownCar);
            }
            if (client == null)
            {
                throw new CustomException($"Unknown Client - Id {parameters.ClientId}", ErrorCode.UnknownClient);
            }
            if (parameters.PickUpDateTime < DateTime.Now)
            {
                throw new CustomException($"PickUpDateTime must be greater than current DateTime", ErrorCode.PickUpDateTimeInThePast);
            }
            if (parameters.PickUpDateTime >= parameters.ReturnDateTime)
            {
                throw new CustomException($"ReturnDateTime must be greater than PickUpDateTime", ErrorCode.ReturnDateTimeBeforePickUpDateTime);
            }

            var pendingReservations = await reservationRep.GetPendingReservationByCarAsync(car.Id, parameters.PickUpDateTime, parameters.ReturnDateTime);

            if (pendingReservations.Any())
            {
                throw new CustomException($"Car is not available in the selected period - CarId {car.Id} - PickUpDateTime {parameters.PickUpDateTime} - ReturnDateTime {parameters.ReturnDateTime} - Existing pending reservation id {pendingReservations.First().Id}", ErrorCode.PendingReservationExists);
            }
        }
        public async Task BookCarReservationAsync_ValidReservation_CreatesNewReservation()
        {
            //Arrange
            var carId               = 200;
            var clientId            = 100;
            var rentalRateFee       = 10;
            var depositFee          = 0.5m;
            var cancellationRateFee = 5;

            var mockedReservationRepository = GetReservationRepositoryWithoutReservation();
            var mockedCarRepository         = GetCarRepositoryWithCar(carId, rentalRateFee, depositFee, cancellationRateFee);
            var mockedClientRepository      = GetClientRepositoryWithClient(clientId);
            var bl = new BLReservation(mockedReservationRepository, mockedCarRepository, mockedClientRepository, mockedUnitOfWork);

            var pickupDateTime = DateTime.Now.AddHours(1);
            var returnDateTime = pickupDateTime.AddHours(10).AddMinutes(30);
            var parameters     = new BookCarReservationParameters()
            {
                CarId          = 200,
                ClientId       = 100,
                PickUpDateTime = pickupDateTime,
                ReturnDateTime = returnDateTime
            };

            //Act
            var reservation = await bl.BookCarReservationAsync(parameters);

            //Assert
            Assert.Equal(10.5m, reservation.DurationInHours);
            Assert.Equal(pickupDateTime, reservation.PickUpDateTime);
            Assert.Equal(returnDateTime, reservation.ReturnDateTime);
            Assert.Equal(carId, reservation.Car.Id);
            Assert.Equal(clientId, reservation.Client.Id);
            Assert.Equal(ReservationState.Booked, reservation.State);
            Assert.Equal(reservation.Car.Type.CancellationRateFee, reservation.ClientAccount.CancellationFeeValueAtBookingMoment);
            Assert.Equal(reservation.Car.Type.RentalRateFee, reservation.ClientAccount.RentalRateFeeValueAtBookingMoment);
            Assert.Equal(reservation.DurationInHours * rentalRateFee * depositFee, reservation.ClientAccount.DepositFeePaid);
        }