/// <summary> /// Check availability /// </summary> /// <param name="returnAvailableOnly">if true will not return unavailability reason rows</param> /// <param name="availabilitySearchCriteria">search criteria for availability search</param> /// <returns>List of rooms available</returns> public List<RoomsAvailability> GetAvailabilityForBusinessesBetweenDates(bool returnAvailableOnly, AvailabilitySearchCriteria availabilitySearchCriteria) { if (availabilitySearchCriteria == null) { return new List<RoomsAvailability>(); } int adults = availabilitySearchCriteria.NumberOfAdults ?? 1; int children = availabilitySearchCriteria.NumberOfChildren ?? 0; // fill in required fields var parameters = new List<SqlParameter> { DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.BusinessList, availabilitySearchCriteria.BusinessIds.ToArray().Serialize(',')), DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.StartDate, availabilitySearchCriteria.StartDate.ConvertToTimeZoneLessDateTime()), DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.EndDate, availabilitySearchCriteria.EndDate.ConvertToTimeZoneLessDateTime()), DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.Adults, adults), DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.Children, children), DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.ReturnAvailableOnly, returnAvailableOnly) }; // add fields that are optional if (availabilitySearchCriteria.RatePlanId.HasValue) { parameters.Add(DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.RatePlanId, availabilitySearchCriteria.RatePlanId.Value)); } if (availabilitySearchCriteria.ModifyBookingId.HasValue) { parameters.Add(DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.ExcludedBookingId, availabilitySearchCriteria.ModifyBookingId.Value)); } if (availabilitySearchCriteria.BoardBasis != null) { parameters.Add(DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.BoardBasisCode, availabilitySearchCriteria.BoardBasis.Code)); } if (availabilitySearchCriteria.CancellationClass != null) { parameters.Add(DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.CancellationClassCode, availabilitySearchCriteria.CancellationClass.Code)); } if (availabilitySearchCriteria.ChannelId.HasValue) { parameters.Add(DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.ChannelId, availabilitySearchCriteria.ChannelId.Value)); } if (availabilitySearchCriteria.RoomTypeId.HasValue) { parameters.Add(DbHelper.CreateParameter(RoomsAvailabilityMapper.Parameters.RoomTypeId, availabilitySearchCriteria.RoomTypeId.Value)); } return DbHelper.CreateInstanceList("Pricing.GetAvailability", RoomsAvailabilityMapper.MapRecord, CommandType.StoredProcedure, parameters); }
public void UpdateAvailabilityWithRateCacheSameCurrencyDoesNotCallExchangeConversionCorrectly() { var manager = new Mock<AvailabilityManager> { CallBase = true }; var searchCriteria = new AvailabilitySearchCriteria { BusinessIds = new List<long> { BUSINESS_ONE }, StartDate = CalendarDate.ConvertToCalendarDate(DateTime.UtcNow.Date), EndDate = CalendarDate.ConvertToCalendarDate(DateTime.UtcNow.Date.AddDays(1)), NumberOfAdults = ADULTS_ONE, NumberOfChildren = CHILDREN_ZERO, RequestedCurrency = CURRENCY_ONE }; var roomsAvailable = new List<RoomsAvailability> { new RoomsAvailability { BusinessId = BUSINESS_ONE, RoomTypeId = ROOMTYPE_ONE, RatePlanId = RATEPLAN_ONE, MaxAdults = ADULTS_ONE, MaxChildren = CHILDREN_ZERO } }; var dictionaryData = new Dictionary<long, List<RateCache>>(); dictionaryData[BUSINESS_ONE] = new List<RateCache> { new RateCache { Date = DateTime.UtcNow.Date, Adults = ADULTS_ONE, Children = CHILDREN_ZERO, CurrencyCode = CURRENCY_ONE, RatePlanId = RATEPLAN_ONE, RoomTypeId = ROOMTYPE_ONE, Rate = 10M, WasRate = 5M, MinStay = 1 } }; // check this is called manager.Setup( m => m.DoExchangeRateConversion(It.IsAny<RoomsAvailability>(), CURRENCY_ONE, CURRENCY_ONE)); manager.Object.UpdateAvailabilityWithRateCache(searchCriteria, roomsAvailable, dictionaryData); // make sure it isn't called manager.Verify( m => m.DoExchangeRateConversion(It.IsAny<RoomsAvailability>(), CURRENCY_ONE, CURRENCY_ONE), Times.Never); }
public void UpdateAvailabilityWithRateCacheSetsCorrectUnavailableReason(AvailabilitySearchCriteria criteria, List<RoomsAvailability> roomsAvailable, List<RateCache> rateCacheAvailable, UnavailabilityReasonCode? expectedUnavailability) { //Setup in test case source var cacheDict = new Dictionary<long, List<RateCache>>(); cacheDict.Add(BUSINESS_ONE, rateCacheAvailable); availabilityManager.UpdateAvailabilityWithRateCache(criteria, roomsAvailable, cacheDict); if (roomsAvailable.Any()) { Assert.AreEqual(expectedUnavailability, roomsAvailable.First().UnavailabilityReason, "unavailability reason did not match"); } }
public void UpdateAvailabilityWithPrepayUpdatesRoomCorrectlyForPrepayValues( List<RoomsAvailability> candidateRooms, AvailabilitySearchCriteria availabilitySearchCriteria, Decimal assertCustomValue ) { //Arrange //Setup in test cases // Act availabilityManager.UpdateAvailabilityWithPrepay(candidateRooms, availabilitySearchCriteria); // Assert Assert.AreEqual(assertCustomValue, candidateRooms.First().CustomDeposit, "custom deposit did not match that of expected result."); }
public void OfflineAvailabilityCheckWhereDatesAreInThePastIsSuccessful() { // Arrange var startDate = new CalendarDate() { Day = 1, Month = 1, Year = 2010 }; var endDate = new CalendarDate() { Day = 2, Month = 1, Year = 2010 }; var searchCriteria = new AvailabilitySearchCriteria { BusinessIds = new List<long> {BUSINESS_ID}, StartDate = startDate, EndDate = endDate, NumberOfAdults = 2, NumberOfChildren = 0, RequestedCurrency = "GBP" }; CacheHelper.StubBusinessCacheSingleBusiness(BUSINESS_ID); Cache.Business.Invalidate(); var currencyDaoMock = new Mock<IBusinessCurrencyDao>(); currencyDaoMock.Setup(cd => cd.GetCurrencies("root")).Returns(new List<Currency> { new Currency("GBP", "£", "pound", 2), new Currency("USD", "$", "dollar", 2) }); Cache.CurrencyCache.Dao = currencyDaoMock.Object; // Make sure the rooms are quickly determined using a GetAvailabileRoomsFor method pricingAvailabilityDao.Setup(x => x.GetAvailabilityForBusinessesBetweenDates(true, It.Is<AvailabilitySearchCriteria>( y => y.Equals(searchCriteria)))) .Returns(new List<RoomsAvailability> {new RoomsAvailability { BusinessId = BUSINESS_ID, Available = 1, BaseRatePlanId = 1, RatePlanId = 2, RoomTypeId = ROOMTYPE_ID, RoomList = new List<int> { 5 }, CurrencyCode = "GBP" }}); rateCacheManager.Setup( rc => rc.GetRatesByBusinessesAndDateRange(It.Is<IEnumerable<long>>(ie => ie.Contains(BUSINESS_ID)), It.Is<DateTime>( d => d.Date == startDate.ConvertToTimeZoneLessDateTime().Date), It.Is<DateTime>( d => d.Date == endDate.ConvertToTimeZoneLessDateTime().Date))).Returns(new Dictionary<long, List<RateCache>>()); try { // Act availabilityManager.CheckAvailability(searchCriteria); } catch { // Assert Assert.Fail("Validation exception should not have been thrown for offline search in past."); } // Assert - see Teardown CacheHelper.ReAssignBusinessDaoToBusinessCache(); }
private void TestCallHasNoEffect(int? modifyBookingId, Booking booking) { //Arrange var criteria = new AvailabilitySearchCriteria { ModifyBookingId = modifyBookingId, RatePlanId = CRITERIA_RATE_PLAN_ID, RoomTypeId = CRITERIA_ROOM_TYPE_ID, BusinessIds = new List<long>{BUSINESS_ID} }; //Act var result = availabilityManager.UpdateCriteriaForExistingBooking(criteria, booking); //Assert Assert.AreEqual(null, result, "Availability incorrectly set to none available"); Assert.AreEqual(CRITERIA_RATE_PLAN_ID, criteria.RatePlanId, "Rate Plan Id Modified Incorrectly"); Assert.AreEqual(CRITERIA_ROOM_TYPE_ID, criteria.RoomTypeId, "Room Type Modified incorrectly"); }
/// <summary> /// Update the available rooms with the correct custom deposit based on prepay rules /// </summary> /// <param name="candidateRooms">rooms from availability</param> /// <param name="availabilitySearchCriteria">criteria for search</param> public void UpdateAvailabilityWithPrepay(IEnumerable<RoomsAvailability> candidateRooms, AvailabilitySearchCriteria availabilitySearchCriteria) { Parallel.ForEach(candidateRooms, room => { switch (room.PrePayType) { case PrePayRuleTypeEnum.Amount: room.CustomDeposit = room.PrePayRuleValue; break; case PrePayRuleTypeEnum.Percentage: room.CustomDeposit = room.TotalRate*(room.PrePayRuleValue/100); break; case PrePayRuleTypeEnum.Nights: var stayLength = availabilitySearchCriteria.EndDate.ConvertToTimeZoneLessDateTime() .Subtract( availabilitySearchCriteria.StartDate .ConvertToTimeZoneLessDateTime()) .Days; if (stayLength > room.PrePayRuleValue) { room.CustomDeposit = (room.TotalRate/stayLength) * room.PrePayRuleValue; } else { room.CustomDeposit = room.TotalRate; } break; } if (room.CustomDeposit > room.TotalRate) { room.CustomDeposit = room.TotalRate; } }); }
private AvailabilitySearchResult FindRoomAndRatePlan(OrderRequestDto order, BookingRequestDto bookingRequest) { Model.Business.Business business = businessManager.GetLimitedBusinessByShortname(order.BusinessShortName); if (business == null) { return null; } var currency = business.WorkingCurrencyCode; AvailabilitySearchCriteria availabilitySearchCriteria = new AvailabilitySearchCriteria { BusinessIds = new List<long> { business.Id }, StartDate = CalendarDate.ConvertToCalendarDate( bookingRequest.StartDate), EndDate = CalendarDate.ConvertToCalendarDate( bookingRequest.EndDate), NumberOfAdults = bookingRequest.NumberOfAdults, NumberOfChildren = bookingRequest.NumberOfChildren, RatePlanId = bookingRequest.RatePlanId, RoomTypeId = bookingRequest.RoomTypeId, RequestedCurrency = currency, ChannelId = order.ChannelId }; // Get the results AvailabilitySearchResult result = availabilityManager.CheckAvailability(availabilitySearchCriteria); return result; }
///// <summary> ///// Check availability for a room type when editing the room of an existing booking ///// </summary> ///// <remarks> ///// Available rooms for a room type and rate plan of an existing booking should be returned. ///// </remarks> //[Test] //public void CheckAvailabilityForRoomTypeWhenEditingRoomOfAnExistingBookingIsReturned() //{ // // Arrange // var availabilityManager = new AvailabilityManager(); // var pricingAvailabilityDao = MockRepository.GenerateStub<IPricingAvailabilityDao>(); // availabilityManager.PricingAvailabilityDao = pricingAvailabilityDao; // // Setup a booking record // var existingBooking = BookingBuilder.SetupSimpleBooking(); // long[] businessIds = new[] { existingBooking.BusinessId }; // CalendarDate startDate = CalendarDate.ConvertToCalendarDate(existingBooking.StartDate); // CalendarDate endDate = CalendarDate.ConvertToCalendarDate(existingBooking.EndDate); // // Build Available rooms // var roomsAvailable = new List<AvailableRoom> // { // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = existingBooking.RoomId // }, // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = 2 // }, // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = 3 // } // }; // pricingAvailabilityDao.Stub(r => r.GetAvailabilityForBusinessesBetweenDates(businessIds, startDate, endDate, // modifyBookingId: existingBooking.Id)).Return(roomsAvailable); // var availableRatePlans = new List<AvailabilityResultRatePlan> // { // new AvailabilityResultRatePlan // { // RatePlanId = 1, // IsAdultOnly = true, // IsBaseRatePlan = true, // MaxAdult = 2, // MaxChild = 0, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // } // }; // var availableRoomType = new AvailabilityResultRoomType // { // BusinessId = existingBooking.BusinessId, // RoomIds = roomsAvailable.Select(x => x.RoomId).ToList(), // RoomTypeCode = "R1", // RoomTypeName = "Double Room", // RoomTypeId = existingBooking.RoomTypeId, // RatesAndRoomsAvailable = availableRatePlans // }; // var roomTypesWithRatePlans = new List<AvailabilityResultRoomType> // { // availableRoomType // }; // var roomTypesWithRatePlansAvailable = new RoomTypesWithRatePlanForAvailableRooms // { // RoomTypesWithRatePlans = roomTypesWithRatePlans // }; // // The dao returns all rateplans available for a roomType. The manager class needs to make sure it filters out rateplans that are not applicable. // pricingAvailabilityDao.Stub(r => r.GetRoomTypesWithRatePlans(businessIds, roomsAvailable, startDate, endDate)).Return(roomTypesWithRatePlansAvailable); // // Stub the BusinessCache to be used by our service method // CacheHelper.StubBusinessCacheSingleBusiness(existingBooking.BusinessId); // // Invalidate the cache so we make sure our business is loaded into the cache // Cache.Business.Invalidate(); // // Build availability Search criteria // var searchCriteria = new AvailabilitySearchCriteria // { // BusinessIds = new List<long> { existingBooking.BusinessId }, // StartDate = startDate, // EndDate = endDate, // NumberOfAdults = existingBooking.NumberOfAdults, // NumberOfChildren = existingBooking.NumberOfChildren, // RoomTypeId = existingBooking.RoomTypeId, // RatePlanId = existingBooking.RatePlanId, // ModifyBookingId = existingBooking.Id // }; // // Act // AvailabilitySearchResult result = availabilityManager.CheckAvailability(searchCriteria); // // Assert // Assert.IsNotNull(result, "AvailabilitySearchResult is null"); // Assert.IsNotNull(result.BusinessCandidates, "Results should be returned."); // AvailabilityResultBusiness businessCandidate = result.BusinessCandidates[0]; // Assert.IsTrue(businessCandidate.BusinessId == existingBooking.BusinessId, "BusinessId returned on search results is incorrect."); // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable.Count, "There should only be one room type."); // Assert.AreEqual(existingBooking.RoomTypeId, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomTypeId, "The returned room type does not match the existing booking."); // Assert.IsNull(result.UnavailabilityReasonCode, "There should not be any unavailable rooms."); // Assert.AreEqual(3, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomIds.Count, "Number of rooms returned is incorrect."); // Assert.IsTrue(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomIds.Contains(existingBooking.RoomId), "Existing RoomId is not in list of rooms."); // Assert.IsNotNull(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable, "RatePlan is not retrieved for roomType."); // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable.Count, "There should only be one rate plan."); // Assert.AreEqual(existingBooking.RatePlanId, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable[0].RatePlanId, "The returned rate plan does not match the existing booking."); // // Reassign the Dao on the cache to discard the stub assigned on the StubBusinessCacheSingleBusiness method // CacheHelper.ReAssignBusinessDaoToBusinessCache(); //} ///// <summary> ///// Check availability for a room type when editing the room and rate plan of an existing booking ///// </summary> ///// <remarks> ///// Available rooms for a room type of an existing booking should be returned. ///// </remarks> //[Test] //public void CheckAvailabilityForRoomTypeWhenEditingRoomAndRatePlanOfAnExistingBookingIsReturned() //{ // // Arrange // var availabilityManager = new AvailabilityManager(); // var pricingAvailabilityDao = MockRepository.GenerateStub<IPricingAvailabilityDao>(); // availabilityManager.PricingAvailabilityDao = pricingAvailabilityDao; // // Setup a booking record // var existingBooking = BookingBuilder.SetupSimpleBooking(); // long[] businessIds = new[] { existingBooking.BusinessId }; // CalendarDate startDate = CalendarDate.ConvertToCalendarDate(existingBooking.StartDate); // CalendarDate endDate = CalendarDate.ConvertToCalendarDate(existingBooking.EndDate); // // Build Available rooms // var roomsAvailable = new List<AvailableRoom> // { // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = existingBooking.RoomId // }, // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = 2 // }, // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = 3 // } // }; // pricingAvailabilityDao.Stub(r => r.GetAvailabilityForBusinessesBetweenDates(businessIds, startDate, endDate, // modifyBookingId: existingBooking.Id)).Return(roomsAvailable); // var availableRatePlans = new List<AvailabilityResultRatePlan> // { // new AvailabilityResultRatePlan // { // RatePlanId = 1, // IsAdultOnly = true, // IsBaseRatePlan = true, // MaxAdult = 2, // MaxChild = 0, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // }, // new AvailabilityResultRatePlan // { // RatePlanId = 2, // IsAdultOnly = false, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 1, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // }, // new AvailabilityResultRatePlan // { // RatePlanId = 3, // IsAdultOnly = false, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 1, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // }, // new AvailabilityResultRatePlan // { // RatePlanId = 4, // IsAdultOnly = true, // IsBaseRatePlan = false, // MaxAdult = 3, // MaxChild = 0, // MaxOccupancy = 3, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // }, // new AvailabilityResultRatePlan // { // RatePlanId = 5, // IsAdultOnly = true, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 0, // MaxOccupancy = 1, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // } // }; // var availableRoomType = new AvailabilityResultRoomType // { // BusinessId = existingBooking.BusinessId, // RoomIds = new List<int> { 1, 2, 3 }, // RoomTypeCode = "R1", // RoomTypeName = "Double Room", // RoomTypeId = existingBooking.RoomTypeId, // RatesAndRoomsAvailable = availableRatePlans // }; // var roomTypesWithRatePlans = new List<AvailabilityResultRoomType> // { // availableRoomType // }; // var roomTypesWithRatePlansAvailable = new RoomTypesWithRatePlanForAvailableRooms // { // RoomTypesWithRatePlans = roomTypesWithRatePlans // }; // // The dao returns all rateplans available for a roomType. The manager class needs to make sure it filters out rateplans that are not applicable. // pricingAvailabilityDao.Stub(r => r.GetRoomTypesWithRatePlans(businessIds, roomsAvailable, startDate, endDate)).Return(roomTypesWithRatePlansAvailable); // // Stub the BusinessCache to be used by our service method // CacheHelper.StubBusinessCacheSingleBusiness(existingBooking.BusinessId); // // Invalidate the cache so we make sure our business is loaded into the cache // Cache.Business.Invalidate(); // // Build availability Search criteria // var searchCriteria = new AvailabilitySearchCriteria // { // BusinessIds = new List<long> { existingBooking.BusinessId }, // StartDate = startDate, // EndDate = endDate, // NumberOfAdults = existingBooking.NumberOfAdults, // NumberOfChildren = existingBooking.NumberOfChildren, // RoomTypeId = existingBooking.RoomTypeId, // ModifyBookingId = existingBooking.Id // }; // // Act // AvailabilitySearchResult result = availabilityManager.CheckAvailability(searchCriteria); // // Assert // Assert.IsNotNull(result, "AvailabilitySearchResult is null"); // Assert.IsNotNull(result.BusinessCandidates, "Results should be returned."); // AvailabilityResultBusiness businessCandidate = result.BusinessCandidates[0]; // Assert.IsTrue(businessCandidate.BusinessId == existingBooking.BusinessId, "BusinessId returned on search results is incorrect."); // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable.Count, "There should only be one room type."); // Assert.IsNull(result.UnavailabilityReasonCode, "There should not be any unavailable rooms."); // Assert.AreEqual(3, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomIds.Count, "Number of rooms returned is incorrect."); // Assert.IsTrue(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomIds.Contains(existingBooking.RoomId), "Existing RoomId is not in list of rooms."); // Assert.IsNotNull(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable, "RatePlan is not retrieved for roomType."); // Assert.AreEqual(5, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable.Count, "Total number of rateplans returned is incorrect."); // // Reassign the Dao on the cache to discard the stub assigned on the StubBusinessCacheSingleBusiness method // CacheHelper.ReAssignBusinessDaoToBusinessCache(); //} ///// <summary> ///// Check availability of rooms when editing the occupancy (and hence, room type and rate plan) of an existing booking ///// </summary> ///// <remarks> ///// Available rooms matching the new occupancy, room type and rate plan for an existing booking should be returned. ///// </remarks> //[Test] //public void CheckAvailabilityOfRoomsWhenEditingOccupancyOfAnExistingBookingIsReturned() //{ // // Arrange // var availabilityManager = new AvailabilityManager(); // var pricingAvailabilityDao = MockRepository.GenerateStub<IPricingAvailabilityDao>(); // availabilityManager.PricingAvailabilityDao = pricingAvailabilityDao; // // Setup a booking record // var existingBooking = BookingBuilder.SetupSimpleBooking(); // long[] businessIds = new[] { existingBooking.BusinessId }; // CalendarDate startDate = CalendarDate.ConvertToCalendarDate(existingBooking.StartDate); // CalendarDate endDate = CalendarDate.ConvertToCalendarDate(existingBooking.EndDate); // // Build Available rooms // var roomsAvailable = new List<AvailableRoom> // { // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = existingBooking.RoomId // }, // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = 2 // }, // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = 3 // }, // new AvailableRoom // { // BusinessId = existingBooking.BusinessId, // RoomId = 7 // } // }; // pricingAvailabilityDao.Stub(r => r.GetAvailabilityForBusinessesBetweenDates(businessIds, startDate, endDate, // modifyBookingId: existingBooking.Id)).Return(roomsAvailable); // var availableRatePlansForRoomType1 = new List<AvailabilityResultRatePlan> // { // new AvailabilityResultRatePlan // { // RatePlanId = 1, // IsAdultOnly = true, // IsBaseRatePlan = true, // MaxAdult = 2, // MaxChild = 0, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = 1 // }, // new AvailabilityResultRatePlan // { // RatePlanId = 2, // IsAdultOnly = false, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 1, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = 1 // }, // new AvailabilityResultRatePlan // { // RatePlanId = 3, // IsAdultOnly = false, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 1, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = 1 // }, // new AvailabilityResultRatePlan // { // RatePlanId = 4, // IsAdultOnly = true, // IsBaseRatePlan = false, // MaxAdult = 3, // MaxChild = 0, // MaxOccupancy = 3, // MinAdult = 1, // RoomTypeId = 1 // }, // new AvailabilityResultRatePlan // { // RatePlanId = 5, // IsAdultOnly = true, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 0, // MaxOccupancy = 1, // MinAdult = 1, // RoomTypeId = 1 // } // }; // var availableRatePlansForRoomType7 = new List<AvailabilityResultRatePlan> // { // new AvailabilityResultRatePlan // { // RatePlanId = 12, // IsAdultOnly = false, // IsBaseRatePlan = true, // MaxAdult = 4, // MaxChild = 2, // MaxOccupancy = 4, // MinAdult = 2, // RoomTypeId = 7 // }, // new AvailabilityResultRatePlan // { // RatePlanId = 13, // IsAdultOnly = true, // IsBaseRatePlan = false, // MaxAdult = 2, // MaxChild = 0, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = 7 // } // }; // var roomTypesWithRatePlans = new List<AvailabilityResultRoomType> // { // new AvailabilityResultRoomType // { // BusinessId = existingBooking.BusinessId, // RoomIds = new List<int> { 1 }, // RoomTypeCode = "R1", // RoomTypeName = "Double Room", // RoomTypeId = existingBooking.RoomTypeId, // RatesAndRoomsAvailable = availableRatePlansForRoomType1 // }, // new AvailabilityResultRoomType // { // BusinessId = existingBooking.BusinessId, // RoomIds = new List<int> { 7 }, // RoomTypeCode = "R4", // RoomTypeName = "Twin Double Room", // RoomTypeId = 7, // RatesAndRoomsAvailable = availableRatePlansForRoomType7 // } // }; // var roomTypesWithRatePlansAvailable = new RoomTypesWithRatePlanForAvailableRooms // { // RoomTypesWithRatePlans = roomTypesWithRatePlans // }; // // The dao returns all rateplans available for a roomType. The manager class needs to make sure it filters out rateplans that are not applicable. // pricingAvailabilityDao.Stub(r => r.GetRoomTypesWithRatePlans(businessIds, roomsAvailable, startDate, endDate)).Return(roomTypesWithRatePlansAvailable); // // Stub the BusinessCache to be used by our service method // CacheHelper.StubBusinessCacheSingleBusiness(existingBooking.BusinessId); // // Invalidate the cache so we make sure our business is loaded into the cache // Cache.Business.Invalidate(); // // Build availability Search criteria // var searchCriteria = new AvailabilitySearchCriteria // { // BusinessIds = new List<long> { existingBooking.BusinessId }, // StartDate = startDate, // EndDate = endDate, // NumberOfAdults = 3, // NumberOfChildren = existingBooking.NumberOfChildren, // ModifyBookingId = existingBooking.Id // }; // // Act // AvailabilitySearchResult result = availabilityManager.CheckAvailability(searchCriteria); // // Assert // Assert.IsNotNull(result, "AvailabilitySearchResult is null"); // Assert.IsNotNull(result.BusinessCandidates, "Results should be returned."); // AvailabilityResultBusiness businessCandidate = result.BusinessCandidates[0]; // Assert.IsTrue(businessCandidate.BusinessId == existingBooking.BusinessId, "BusinessId returned on search results is incorrect."); // Assert.AreEqual(2, businessCandidate.RoomTypesRatesAndRoomsAvailable.Count, "Total number of room types returned is incorrect."); // Assert.IsNull(result.UnavailabilityReasonCode, "There should not be any unavailable rooms."); // // Room type 1 // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomIds.Count, "Number of rooms returned is incorrect."); // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomTypeId, "The room type returned is incorrect."); // Assert.IsNotNull(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable, "RatePlan is not retrieved for roomType."); // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable.Count, "Total number of rateplans returned is incorrect."); // Assert.AreEqual(4, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable[0].RatePlanId, "The rate plan returned is incorrect."); // Assert.AreEqual(UnavailabilityReasonCode.NoRateDefined, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].UnAvailabilityReasonCode, "UnAvailabilityReasonCode at RoomType level is incorrect."); // // Room type 7 // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable[1].RoomIds.Count, "Number of rooms returned is incorrect."); // Assert.AreEqual(7, businessCandidate.RoomTypesRatesAndRoomsAvailable[1].RoomTypeId, "The room type returned is incorrect."); // Assert.IsNotNull(businessCandidate.RoomTypesRatesAndRoomsAvailable[1].RatesAndRoomsAvailable, "RatePlan is not retrieved for roomType."); // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable[1].RatesAndRoomsAvailable.Count, "Total number of rateplans returned is incorrect."); // Assert.AreEqual(12, businessCandidate.RoomTypesRatesAndRoomsAvailable[1].RatesAndRoomsAvailable[0].RatePlanId, "The rate plan returned is incorrect."); // Assert.AreEqual(UnavailabilityReasonCode.NoRateDefined, businessCandidate.RoomTypesRatesAndRoomsAvailable[1].UnAvailabilityReasonCode, "UnAvailabilityReasonCode at RoomType level is incorrect."); // // Reassign the Dao on the cache to discard the stub assigned on the StubBusinessCacheSingleBusiness method // CacheHelper.ReAssignBusinessDaoToBusinessCache(); //} ///// <summary> ///// Check availability ahead of a Change rateplan of booking while retaining the RoomStyle edit. ///// The parameters submitted for availability check will be: ///// ///// start Date (same as existing) ///// End date (same as existing) ///// Number of adults (same as existing) ///// Number of Children (same as existing) ///// Room Type (same as existing) ///// Room ID (same as existing) ///// </summary> ///// <remarks> ///// All rateplans applicable to the RoomType which satisfy occupancy criteria should be returned ///// </remarks> //[Test] //public void CheckAvailabilityToChangeRatePlanOfBookingReturnsAllRatePlansApplicable() //{ // // Arrange // AvailabilityManager availabilityManager = new AvailabilityManager(); // IPricingAvailabilityDao pricingAvailabilityDao = MockRepository.GenerateStub<IPricingAvailabilityDao>(); // availabilityManager.PricingAvailabilityDao = pricingAvailabilityDao; // // Setup a booking record // Booking existingBooking = new Booking() // { // Id = 1, // BusinessId = 1, // RoomTypeId = 1, // RoomId = 2, // RatePlanId = 3, // StartDate = DateTime.UtcNow, // EndDate = DateTime.UtcNow.AddDays(1), // NumberOfAdults = 1, // NumberOfChildren = 1 // }; // long[] businessIds = new long[] { existingBooking.BusinessId }; // CalendarDate startDate = CalendarDate.ConvertToCalendarDate(existingBooking.StartDate); // CalendarDate endDate = CalendarDate.ConvertToCalendarDate(existingBooking.EndDate); // // Build Available rooms // List<AvailableRoom> roomsAvailable = new List<AvailableRoom>() // { // new AvailableRoom() // { // BusinessId = existingBooking.BusinessId, // RoomId = existingBooking.RoomId // } // }; // pricingAvailabilityDao.Stub( // r => // r.GetAvailabilityForBusinessesBetweenDates(businessIds, startDate, endDate, existingBooking.RoomId, // existingBooking.Id)).Return(roomsAvailable); // // Build available RoomTypesRatesAndRoomsAvailable And RatesAndRoomsAvailable // // There are 5 rateplans (1 base rateplan and 4 additional rateplans) available for a roomType // AvailabilityResultRatePlan ratePlan2AdBaseRatePlan = new AvailabilityResultRatePlan() // { // RatePlanId = 1, // IsAdultOnly = true, // IsBaseRatePlan = true, // MaxAdult = 2, // MaxChild = 0, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // }; // AvailabilityResultRatePlan ratePlan1Ad1ChWithBreakfast = new AvailabilityResultRatePlan() // { // RatePlanId = 2, // IsAdultOnly = false, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 1, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // }; // AvailabilityResultRatePlan ratePlan1Ad1ChWithOutBreakfast = new AvailabilityResultRatePlan() // { // RatePlanId = 3, // IsAdultOnly = false, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 1, // MaxOccupancy = 2, // MinAdult = 1, // RoomTypeId = // existingBooking.RoomTypeId // }; // AvailabilityResultRatePlan ratePlan3Ad = new AvailabilityResultRatePlan() // { // IsAdultOnly = true, // IsBaseRatePlan = false, // MaxAdult = 3, // MaxChild = 0, // MaxOccupancy = 3, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // }; // AvailabilityResultRatePlan ratePlan1Ad = new AvailabilityResultRatePlan() // { // IsAdultOnly = true, // IsBaseRatePlan = false, // MaxAdult = 1, // MaxChild = 0, // MaxOccupancy = 1, // MinAdult = 1, // RoomTypeId = existingBooking.RoomTypeId // }; // List<AvailabilityResultRatePlan> ratePlansAvailable = new List<AvailabilityResultRatePlan>() // { // ratePlan2AdBaseRatePlan, // ratePlan1Ad1ChWithBreakfast, // ratePlan1Ad1ChWithOutBreakfast, // ratePlan3Ad, // ratePlan1Ad // }; // AvailabilityResultRoomType availabilityResultRoomType = new AvailabilityResultRoomType() // { // BusinessId = existingBooking.BusinessId, // RoomIds = new List<int>() { existingBooking.RoomId }, // RatesAndRoomsAvailable = ratePlansAvailable, // RoomTypeId = existingBooking.RoomTypeId, // }; // List<AvailabilityResultRoomType> roomTypesWithRatePlans = new List<AvailabilityResultRoomType>() // { // availabilityResultRoomType // }; // RoomTypesWithRatePlanForAvailableRooms roomTypesWithRatePlansAvailable = // new RoomTypesWithRatePlanForAvailableRooms() { RoomTypesWithRatePlans = roomTypesWithRatePlans }; // // The dao returns all rateplans available for a roomType. The manager class needs to make sure it filters out rateplans that are not applicable. // pricingAvailabilityDao.Stub( // r => r.GetRoomTypesWithRatePlans(businessIds, roomsAvailable, startDate, endDate)).Return( // roomTypesWithRatePlansAvailable); // // Note: we are not mocking DRM repository here because Price, Price is not a mandatory check to be made in edit process. // // A room can still be returned as available when there is no price defined. // // Stub the BusinessCache to be used by our service method // CacheHelper.StubBusinessCacheSingleBusiness(existingBooking.BusinessId); // // invalidate the cache so we make sure our business is loaded into the cache // Cache.Business.Invalidate(); // // Build availability Search criteria // AvailabilitySearchCriteria searchCriteria = new AvailabilitySearchCriteria() // { // BusinessIds = // new List<long>() { existingBooking.BusinessId }, // StartDate = startDate, // EndDate = endDate, // NumberOfAdults = existingBooking.NumberOfAdults, // NumberOfChildren = existingBooking.NumberOfChildren, // RoomTypeId = existingBooking.RoomTypeId, // RoomId = existingBooking.RoomId, // ModifyBookingId = existingBooking.Id // }; // // Act // AvailabilitySearchResult searchResult = availabilityManager.CheckAvailability(searchCriteria); // // Assert // Assert.IsNotNull(searchResult, "AvailabilitySearchResult is null"); // Assert.AreEqual(1, searchResult.BusinessCandidates.Count, "Total number of business candidates returned is incorrect."); // Assert.IsTrue(searchResult.BusinessCandidates[0].BusinessId == existingBooking.BusinessId, "BusinessId returned on search results is incorrect."); // AvailabilityResultBusiness businessCandidate = searchResult.BusinessCandidates[0]; // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable.Count, "Number of roomTypes returned is incorrect."); // Assert.AreEqual(existingBooking.RoomTypeId, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomTypeId, "RoomTypeId returned is incorrect."); // Assert.AreEqual(1, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomIds.Count, "Number of rooms returned is incorrect."); // Assert.AreEqual(existingBooking.RoomId, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RoomIds[0], "RoomId returned is incorrect."); // // Check Rateplans // // There are 5 total rateplans present for the roomType requested. We need to make sure only ratePlan1Ad1ChWithBreakfast, ratePlan1Ad1ChWithOutBreakfast rateplans are returned as available // Assert.AreEqual(2, businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable.Count, "Total number of rateplans returned is incorrect."); // Assert.IsNotNull(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable.Find(r => r.RatePlanId == ratePlan1Ad1ChWithBreakfast.RatePlanId), "The rateplan for which the booking is made is not returned as available."); // Assert.IsNotNull(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable.Find(r => r.RatePlanId == ratePlan1Ad1ChWithOutBreakfast.RatePlanId), "Additional rateplan is not returned as available."); // Assert.IsNotNull(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable.Find(r => r.RatePlanId == existingBooking.RatePlanId), "The rateplan for which the booking is made is not returned as available."); // Assert.IsNotNull(businessCandidate.RoomTypesRatesAndRoomsAvailable[0].RatesAndRoomsAvailable.Find(r => r.RatePlanId != existingBooking.RatePlanId), "Additional rateplan is not returned as available."); // // Reassign the Dao on the cache to discard the stub assigned on the StubBusinessCacheSingleBusiness method // CacheHelper.ReAssignBusinessDaoToBusinessCache(); //} ///// <summary> ///// Checks that check availability is called with the correct search criteria ///// </summary> ///// <remarks> ///// No Mocking, since it is a test to make sure search criteria ///// and then the results should match that of check availability ///// </remarks> //[Test] //public void CheckAvailabilityForBookingModifyCallsCheckAvailabilityWithCorrectSearchResultsReturned() //{ // //Arrange // AvailabilityManager availabilityManager = new AvailabilityManager(); // AvailabilitySearchCriteria expectedSearchCriteria = new AvailabilitySearchCriteria(); // BookingDao bookingDao = new BookingDao(); // using (new TestDataHelper(TestDataQueriesLimited.PopulateBookingsAndCloseOutsTestData, GetTestQuery(TestQuery.CleanupUnitTestData))) // { // // Arrange // const int bookingId = 1; // // Get the existing booking to check against // Booking updatedBooking = bookingDao.GetByKey(bookingId); // // change data on booking // updatedBooking.StartDate = updatedBooking.StartDate.AddDays(1); // updatedBooking.EndDate = updatedBooking.EndDate.AddDays(1); // // Set up search criteria based on booking // expectedSearchCriteria = GetExpectedSearchCriteriaFromBooking(updatedBooking); // // Act // AvailabilitySearchResult searchResultFromBookingModify = // availabilityManager.CheckAvailabilityForBookingModify(updatedBooking); // AvailabilitySearchResult searchResultFromCheckAvailability = // availabilityManager.CheckAvailability(expectedSearchCriteria); // // Assert, only one result since just checking the information from the existing booking // CheckSearchResultsMatch(searchResultFromCheckAvailability, searchResultFromBookingModify); // } //} ///// <summary> ///// Checks that check availability with only start date, end date, number of adults, and number of children works. ///// </summary> ///// <remarks> ///// Checks that existing booking doesn't block availability and otherwise does an availability check. ///// </remarks> //[Test] //public void CheckAvailabilityForExistingBookingWithChangeOfRoomTypeCallsCheckAvailabilityWithCorrectSearchResultsReturned() //{ // // Arrange // AvailabilityManager availabilityManager = new AvailabilityManager(); // IPricingAvailabilityDao pricingAvailabilityDao = MockRepository.GenerateStub<IPricingAvailabilityDao>(); // availabilityManager.PricingAvailabilityDao = pricingAvailabilityDao; // int businessId = 1; // int totalNumberOfRooms = 4; // int numberOfRoomTypes = 2; // long[] businessIds = new long[] {businessId}; // // Set up a simple booking // Booking booking = BookingBuilder.SetupSimpleBooking(); // // make it a bit different // booking.RoomId = 3; // booking.RoomTypeId = 2; // booking.NumberOfAdults = 2; // booking.RatePlanId = 2; // booking.NumberOfChildren = 0; // booking.StartDate = DateTime.UtcNow.AddDays(1); // booking.EndDate = booking.StartDate.AddDays(1); // // Set up the results // RoomTypesWithRatePlanForAvailableRooms roomTypesWithRatePlanForAvailableRooms = // RoomTypesWithRatePlansForAvailableRoomsBuilder.Build(businessId: businessId, numberOfRatePlansPerRoomType: 3, // maxRoomTypeId: numberOfRoomTypes, // numberOfRoomsPerRoomType: totalNumberOfRooms / numberOfRoomTypes); // List<AvailableRoom> availableRooms = new List<AvailableRoom>(); // for(int roomId = 1; roomId <= totalNumberOfRooms; roomId++) // { // availableRooms.Add(new AvailableRoom() // { // BusinessId = businessId, // RoomId = roomId // }); // } // // set up two search criteria with start / end date and number of adults / number of children. // AvailabilitySearchCriteria availabilitySearchCriteriaWithBooking = new AvailabilitySearchCriteria(); // availabilitySearchCriteriaWithBooking.BusinessIds = businessIds.ToList(); // availabilitySearchCriteriaWithBooking.StartDate = CalendarDate.ConvertToCalendarDate(booking.StartDate); // availabilitySearchCriteriaWithBooking.EndDate = CalendarDate.ConvertToCalendarDate(booking.EndDate); // availabilitySearchCriteriaWithBooking.NumberOfAdults = booking.NumberOfAdults; // availabilitySearchCriteriaWithBooking.NumberOfChildren = booking.NumberOfChildren; // availabilitySearchCriteriaWithBooking.ModifyBookingId = booking.Id; // pricingAvailabilityDao.Stub(rad => rad.GetAvailabilityForBusinessesBetweenDates(businessIds, // availabilitySearchCriteriaWithBooking.StartDate, // availabilitySearchCriteriaWithBooking.EndDate, // null, // booking.Id)).Return(availableRooms); // pricingAvailabilityDao.Stub( // rad => // rad.GetRoomTypesWithRatePlans(businessIds, availableRooms, availabilitySearchCriteriaWithBooking.StartDate, // availabilitySearchCriteriaWithBooking.EndDate)).Return(roomTypesWithRatePlanForAvailableRooms); // // Stub the BusinessCache to be used by our service method // CacheHelper.StubBusinessCacheSingleBusiness(businessId); // // invalidate the cache so we make sure our business is loaded into the cache // Cache.Business.Invalidate(); // // Act // // call checkAvailability with given search criteria // AvailabilitySearchResult searchResult = availabilityManager.CheckAvailability(availabilitySearchCriteriaWithBooking); // // Assert // // check that all rooms, rate plans, and room types return according to occupancy / start and end dates // // this includes room from original booking // Assert.IsNotNull(searchResult.BusinessCandidates, "Results should be returned"); // Assert.AreEqual(1, searchResult.BusinessCandidates.Count, "Only one business should be returned"); // Assert.AreEqual(businessId, searchResult.BusinessCandidates[0].BusinessId, "Business id did not match"); // Assert.IsFalse(searchResult.BusinessCandidates[0].UnavailabilityReasonCode.HasValue, "Business should be available"); // Assert.AreEqual(numberOfRoomTypes, searchResult.BusinessCandidates[0].RoomTypesRatesAndRoomsAvailable.Count, // "More than just the original room type should be found"); // Assert.IsTrue( // searchResult.BusinessCandidates[0].RoomTypesRatesAndRoomsAvailable.Exists(rt => rt.RoomIds.Contains(booking.RoomId)), // "A room type with the original room id should be returned"); // // Make sure a room type with the rate plan from the original booking still exists // Assert.IsTrue( // searchResult.BusinessCandidates[0].RoomTypesRatesAndRoomsAvailable.Exists( // rt => rt.RatesAndRoomsAvailable.Exists(rp => rp.RatePlanId == booking.RatePlanId)), // "A room type with the original rate plan was not returned in the results"); // // Make sure that other rate plans also get returned // Assert.IsTrue( // searchResult.BusinessCandidates[0].RoomTypesRatesAndRoomsAvailable.Exists( // rt => rt.RatesAndRoomsAvailable.Exists(rp => rp.RatePlanId != booking.RatePlanId)), // "A room type with a different rate plan than the original was not returned in the results"); // // Reassign the Dao on the cache to discard the stub assigned on the StubBusinessCacheSingleBusiness method // CacheHelper.ReAssignBusinessDaoToBusinessCache(); //} //#endregion //#region CheckOnlineAvailability ///// <summary> ///// Test that correct information is sent to CheckAvailability and that MinStayCriteriaNotMet and NoRateDefined ///// Unavailability reasons don't get returned ///// </summary> ///// <remarks> ///// Mocks the inner search availability so that it only needs check for logic done in ///// the tested method. ///// Uses dummy search criteria and results ///// </remarks> //[Test] //public void CheckAvailabilityForOnlineBusinessLogicCallsCorrectMethodsAndFiltersSuccessfully() //{ // // Arrange // const long BUSINESS_ID = 500; // const string BUSINESS_NAME = "EVO"; // // Set up cache // CacheHelper.StubBusinessCacheSingleBusiness(BUSINESS_ID, BUSINESS_NAME); // // search criteria to use // CalendarDate dummyStartDate = new CalendarDate { Year = DateTime.Now.Year, Month = DateTime.Now.Month, Day = DateTime.Now.Day }; // CalendarDate dummyEndDate = new CalendarDate { Year = DateTime.Now.AddDays(1).Year, Month = DateTime.Now.AddDays(1).Month, Day = DateTime.Now.AddDays(1).Day }; // int NUMBER_OF_ADULTS = 1; // int NUMBER_OF_CHILDREN = 0; // Model.Room.Online.AvailabilitySearchCriteria searchCriteriaToUse = new Model.Room.Online.AvailabilitySearchCriteria // { // BusinessShortNames = new List<string> { BUSINESS_NAME }, // StartDate = dummyStartDate, // EndDate = dummyEndDate, // RoomSearchCriteria = new List<Model.Room.Online.RoomRestrictions> // { // new Model.Room.Online.RoomRestrictions { NumberOfChildren = NUMBER_OF_CHILDREN, NumberOfAdults = NUMBER_OF_ADULTS } // } // }; // // room types // List<AvailabilityResultRoomType> expectedRoomTypes = new List<AvailabilityResultRoomType> // { // new AvailabilityResultRoomType // { // BusinessId = BUSINESS_ID, // RoomIds = new List<int>{ 1, 2, 3, 4 }, // RoomTypeCode = "ONE", // RoomTypeId = 1, // RoomTypeName = "I am room type One", // OnlineRoomAvailability = new Dictionary<int,bool>{{1, true}, {2, false},{3, true},{4, true}}, // RatesAndRoomsAvailable = new List<AvailabilityResultRatePlan>() // }, // new AvailabilityResultRoomType // { // BusinessId = BUSINESS_ID, // RoomIds = new List<int>{ 5, 6 }, // RoomTypeCode = "TWO", // RoomTypeId = 2, // RoomTypeName = "I am room type Two", // OnlineRoomAvailability = new Dictionary<int,bool>{{5, true}, {6, true}}, // UnAvailabilityReasonCode = UnavailabilityReasonCode.MinStayCriteriaNotMet, // RatesAndRoomsAvailable = new List<AvailabilityResultRatePlan>() // }, // new AvailabilityResultRoomType // { // BusinessId = BUSINESS_ID, // RoomIds = new List<int>{ 7, 8 }, // OnlineRoomAvailability = new Dictionary<int,bool>{{7, true}, {8, true}}, // RoomTypeCode = "THREE", // RoomTypeId = 3, // RoomTypeName = "I am room type Three", // UnAvailabilityReasonCode = UnavailabilityReasonCode.NoRateDefined, // RatesAndRoomsAvailable = new List<AvailabilityResultRatePlan>() // }, // new AvailabilityResultRoomType // { // BusinessId = BUSINESS_ID, // RoomIds = new List<int>{ 9, 10 }, // OnlineRoomAvailability = new Dictionary<int,bool>{{9, false}, {10, false}}, // RoomTypeCode = "FOUR", // RoomTypeId = 4, // RoomTypeName = "I am room type Four", // RatesAndRoomsAvailable = new List<AvailabilityResultRatePlan>() // } // }; // // business // AvailabilityResultBusiness expectedResultBusiness = new AvailabilityResultBusiness // { // BusinessId = BUSINESS_ID, // ShortName = BUSINESS_NAME, // RoomTypesRatesAndRoomsAvailable = expectedRoomTypes, // UnavailabilityReasonCode = null // }; // // Set up results from inner search criteria // AvailabilitySearchResult expectedResult = new AvailabilitySearchResult // { // BusinessCandidates = new List<AvailabilityResultBusiness> { expectedResultBusiness }, // StartDate = dummyStartDate, // EndDate = dummyEndDate, // NoOfChildren = NUMBER_OF_CHILDREN, // NoOfAdults = NUMBER_OF_ADULTS, // UnavailabilityReasonCode = null // }; // // Set up Mock so that inner CheckAvailability is mocked // AvailabilityManager mockOfManager = MockRepository.GeneratePartialMock<AvailabilityManager>(); // mockOfManager.Expect(m => m.CheckAvailability(Arg<AvailabilitySearchCriteria>.Matches( // asc => asc.NumberOfAdults == NUMBER_OF_ADULTS && // asc.NumberOfChildren == NUMBER_OF_CHILDREN && // asc.StartDate == searchCriteriaToUse.StartDate && // asc.EndDate == searchCriteriaToUse.EndDate && // asc.BusinessIds.Contains(BUSINESS_ID)) // )).Return(expectedResult).Repeat.Once(); // // Act // AvailabilitySearchResult resultOfSearch = mockOfManager.CheckOnlineAvailability(searchCriteriaToUse); // // Assert // mockOfManager.VerifyAllExpectations(); // Assert.AreEqual(NUMBER_OF_ADULTS, resultOfSearch.NoOfAdults, "Number of adults didn't translate correctly"); // Assert.AreEqual(NUMBER_OF_CHILDREN, resultOfSearch.NoOfChildren, "Number of children didn't translate correctly"); // Assert.AreEqual(dummyStartDate, resultOfSearch.StartDate, "Start date didn't translate correctly"); // Assert.AreEqual(dummyEndDate, resultOfSearch.EndDate, "End date didn't translate correctly"); // Assert.AreEqual(3, resultOfSearch.BusinessCandidates[0].RoomTypesRatesAndRoomsAvailable.Find(rt => rt.RoomTypeId == 1).RoomIds.Count, "Only 3 of the 4 rooms should have returned because of isOnlineAvailable status"); // //Check how the room type where all rooms marked as offline returns // AvailabilityResultRoomType emptyRoomType = resultOfSearch.BusinessCandidates[0].RoomTypesRatesAndRoomsAvailable.Find(rt => rt.RoomTypeId == 4); // Assert.IsNull(emptyRoomType, "Room type should not be returned if all rooms marked as not available online"); // Assert.IsTrue(resultOfSearch.BusinessCandidates.TrueForAll(bc => bc.RoomTypesRatesAndRoomsAvailable.TrueForAll(rt => rt.UnAvailabilityReasonCode.HasValue == false)), // "Unavailability Reasons were not filtered correctly"); // CacheHelper.ReAssignBusinessDaoToBusinessCache(); //} ///// <summary> ///// Make sure that check availability returns no availability when only unavailable for minstay or noratedefined ///// </summary> ///// <remarks> ///// Sets up results that are unavailable for minimum stay criteria and no rate defined ///// then check that it is not available at business level ///// </remarks> //[Test] //public void CheckAvailabilityForOnlineBusinessLogicReturnsNoAvailabilityIsSuccessful() //{ // // Arrange // const long BUSINESS_ID = 500; // const string BUSINESS_NAME = "EVO"; // // Set up cache // CacheHelper.StubBusinessCacheSingleBusiness(BUSINESS_ID, BUSINESS_NAME); // // search criteria to use // CalendarDate dummyStartDate = new CalendarDate { Year = DateTime.Now.Year, Month = DateTime.Now.Month, Day = DateTime.Now.Day }; // CalendarDate dummyEndDate = new CalendarDate { Year = DateTime.Now.AddDays(1).Year, Month = DateTime.Now.AddDays(1).Month, Day = DateTime.Now.AddDays(1).Day }; // int NUMBER_OF_ADULTS = 1; // int NUMBER_OF_CHILDREN = 0; // Model.Room.Online.AvailabilitySearchCriteria searchCriteriaToUse = new Model.Room.Online.AvailabilitySearchCriteria // { // BusinessShortNames = new List<string> { BUSINESS_NAME }, // StartDate = dummyStartDate, // EndDate = dummyEndDate, // RoomSearchCriteria = new List<Model.Room.Online.RoomRestrictions> // { // new Model.Room.Online.RoomRestrictions { NumberOfChildren = NUMBER_OF_CHILDREN, NumberOfAdults = NUMBER_OF_ADULTS } // } // }; // // room types that are unavailable // List<AvailabilityResultRoomType> expectedRoomTypes = new List<AvailabilityResultRoomType> // { // new AvailabilityResultRoomType // { // BusinessId = BUSINESS_ID, // RoomIds = new List<int>{ 5, 6 }, // RoomTypeCode = "TWO", // RoomTypeId = 2, // RoomTypeName = "I am room type Two", // UnAvailabilityReasonCode = UnavailabilityReasonCode.MinStayCriteriaNotMet, // RatesAndRoomsAvailable = new List<AvailabilityResultRatePlan>() // }, // new AvailabilityResultRoomType // { // BusinessId = BUSINESS_ID, // RoomIds = new List<int>{ 7, 8 }, // RoomTypeCode = "THREE", // RoomTypeId = 3, // RoomTypeName = "I am room type Three", // UnAvailabilityReasonCode = UnavailabilityReasonCode.NoRateDefined, // RatesAndRoomsAvailable = new List<AvailabilityResultRatePlan>() // } // }; // // business // AvailabilityResultBusiness expectedResultBusiness = new AvailabilityResultBusiness // { // BusinessId = BUSINESS_ID, // ShortName = BUSINESS_NAME, // RoomTypesRatesAndRoomsAvailable = expectedRoomTypes, // UnavailabilityReasonCode = null // }; // // Set up results from inner search criteria // AvailabilitySearchResult expectedResult = new AvailabilitySearchResult // { // BusinessCandidates = new List<AvailabilityResultBusiness> { expectedResultBusiness }, // StartDate = dummyStartDate, // EndDate = dummyEndDate, // NoOfChildren = NUMBER_OF_CHILDREN, // NoOfAdults = NUMBER_OF_ADULTS, // UnavailabilityReasonCode = null // }; // // Set up Mock so that inner CheckAvailability is mocked // AvailabilityManager mockOfManager = MockRepository.GeneratePartialMock<AvailabilityManager>(); // mockOfManager.Expect(m => m.CheckAvailability(Arg<AvailabilitySearchCriteria>.Matches( // asc => asc.NumberOfAdults == NUMBER_OF_ADULTS && // asc.NumberOfChildren == NUMBER_OF_CHILDREN && // asc.StartDate == searchCriteriaToUse.StartDate && // asc.EndDate == searchCriteriaToUse.EndDate && // asc.BusinessIds.Contains(BUSINESS_ID)) // )).Return(expectedResult).Repeat.Once(); // // Act // AvailabilitySearchResult actualResult = mockOfManager.CheckOnlineAvailability(searchCriteriaToUse); // // Assert // mockOfManager.VerifyAllExpectations(); // Assert.AreEqual(UnavailabilityReasonCode.NoInventory, actualResult.UnavailabilityReasonCode, "Results were not marked as not available"); // Assert.AreEqual(UnavailabilityReasonCode.NoInventory, actualResult.BusinessCandidates[0].UnavailabilityReasonCode, "Business was not marked as unavailable"); // Assert.AreEqual(0, actualResult.BusinessCandidates[0].RoomTypesRatesAndRoomsAvailable.Count, "Room types were returned when no availability"); // CacheHelper.ReAssignBusinessDaoToBusinessCache(); //} ///// <summary> ///// The online availability check requires that the dates are in the future ///// </summary> ///// <remarks> ///// Verifies a Validation Exception is thrown if the dates to check is in the past ///// </remarks> //[Test] //public void OnlineAvailabilityCheckWhereDatesAreInThePastThrowsValidationException() //{ // // Arrange // AvailabilityManager availabilityManager = new AvailabilityManager(); // long businessId = 1; // string businessName = "EVO"; // // Stub the BusinessCache to be used by our service method // CacheHelper.StubBusinessCacheSingleBusiness(businessId, businessName); // // Invalidate the cache so we make sure our business is loaded into the cache // Cache.InvalidateAll(); // try // { // // Act // availabilityManager.CheckOnlineAvailability(new Model.Room.Online.AvailabilitySearchCriteria // { // BusinessShortNames = new List<string>() { businessName }, // StartDate = new CalendarDate() // { // Day = 1, // Month = 1, // Year = 2010 // }, // EndDate = new CalendarDate() // { // Day = 4, // Month = 1, // Year = 2010 // }, // RoomSearchCriteria = new List<Model.Room.Online.RoomRestrictions> // { // new Model.Room.Online.RoomRestrictions // { // NumberOfAdults = 1, // NumberOfChildren = 0 // } // } // }); // // Assert // Assert.Fail("Expected validation code SRVEX30036 which has not been thrown"); // } // catch (ValidationException ex) // { // // Assert // Assert.AreEqual("SRVEX30036", ex.Code, "Check that the correct validation code was raised for dates in the past"); // } // // Reassign the Dao on the cache to discard the stub assigned on the StubBusinessCacheSingleBusiness method // CacheHelper.ReAssignBusinessDaoToBusinessCache(); //} #endregion #region Private Methods /// <summary> /// gets expected search criteria for modify booking search /// </summary> /// <param name="updatedBooking">booking to use to generate search</param> /// <returns>search criteria</returns> private AvailabilitySearchCriteria GetExpectedSearchCriteriaFromBooking(Booking updatedBooking) { AvailabilitySearchCriteria expectedSearchCriteria = new AvailabilitySearchCriteria(); expectedSearchCriteria.NumberOfChildren = updatedBooking.NumberOfChildren; expectedSearchCriteria.NumberOfAdults = updatedBooking.NumberOfAdults; expectedSearchCriteria.ModifyBookingId = updatedBooking.Id; expectedSearchCriteria.StartDate = CalendarDate.ConvertToCalendarDate(updatedBooking.StartDate); expectedSearchCriteria.EndDate = CalendarDate.ConvertToCalendarDate(updatedBooking.EndDate); expectedSearchCriteria.RatePlanId = updatedBooking.RatePlanId; expectedSearchCriteria.RoomTypeId = updatedBooking.RoomTypeId; expectedSearchCriteria.BusinessIds = new List<long>() { updatedBooking.BusinessId }; //expectedSearchCriteria.RequestedCurrency = updatedBooking.CurrencyCode; return expectedSearchCriteria; }
public AvailabilitySearchResultDto CheckAvailability(string propertyId, DateTime startDate, DateTime endDate, int numAdults, int numChildren, int bookingId) { Log.LogDebug( string.Format( "CheckAvailability{0}propertyId: {1}{0}startDate: {2}{0}endDate: {3}{0}numAdults: {4}{0}numChildren: {5}{0}bookingId: {6}", Environment.NewLine, propertyId, startDate, endDate, numAdults, numChildren, bookingId)); int? actualBookingId = null; // Set the culture for number formatting from business (use business culture) GetAndSetCulture(overrideFromUser: false); // check the business id var business = CheckAndGetBusiness(propertyId, GetMethodName()); // if we have a booking id assign it as the REST services do not allow nullable parameters so if its not supplied value will be 0 if (bookingId != default(int)) { actualBookingId = bookingId; } // Convert the search criteria to a model object var criteria = new AvailabilitySearchCriteria { BusinessIds = new List<long> { business.Id }, EndDate = new CalendarDate { Day = endDate.Date.Day, Month = endDate.Date.Month, Year = endDate.Date.Year }, ModifyBookingId = actualBookingId, NumberOfAdults = numAdults, NumberOfChildren = numChildren, StartDate = new CalendarDate { Day = startDate.Date.Day, Month = startDate.Date.Month, Year = startDate.Date.Year }, RequestedCurrency = business.WorkingCurrencyCode }; // Get the results var result = availabilityManager.CheckAvailability(criteria); // If there's an unavailability reason code at the business level then no availability for entire business if (result.UnavailabilityReasonCode.HasValue || result.BusinessCandidates[0].UnavailabilityReasonCode.HasValue) { throw new ValidationException(ErrorFactory.CreateAndLogError(Errors.SRVEX30116, GetMethodName(), additionalDescriptionParameters: (new object[] { business.Id }))); } // For mobile search there will only ever be 1 business so use the first in the result var businessResult = result.BusinessCandidates[0]; // Return the mapped availability for the business return Mapper.Map<AvailabilityResultBusiness, AvailabilitySearchResultDto>(businessResult); }
/// <summary> /// adds the roomtype to the business specified, does some unavailability logic too /// </summary> /// <param name="currentRoomType">current room type</param> /// <param name="currentBusiness">current business</param> /// <param name="availabilitySearchCriteria">original search criteria</param> private void AddRoomTypeToBusiness(AvailabilityResultRoomType currentRoomType, AvailabilityResultBusiness currentBusiness, AvailabilitySearchCriteria availabilitySearchCriteria) { // add room type and business of last business / room type if (currentRoomType != null) { // filter up unavailability if (currentRoomType.RatesAndRoomsAvailable.Max(rt => rt.RoomList != null ? rt.RoomList.Count : 0) == 0 || currentRoomType.RatesAndRoomsAvailable.TrueForAll(rt => rt.UnavailabilityReason.HasValue)) { currentRoomType.UnAvailabilityReasonCode = currentRoomType.RatesAndRoomsAvailable.Min(rt => rt.UnavailabilityReason); } currentBusiness.RoomTypes.Add(currentRoomType); } }
/// <summary> /// Used to fill negative default availability result /// </summary> /// <param name="availabilitySearchCriteria">search criteria used</param> /// <returns>negative default search result</returns> private AvailabilitySearchResult GetNullBusinessAvailabilityResult(AvailabilitySearchCriteria availabilitySearchCriteria) { return new AvailabilitySearchResult() { StartDate = availabilitySearchCriteria.StartDate, EndDate = availabilitySearchCriteria.EndDate, NoOfAdults = availabilitySearchCriteria.NumberOfAdults, NoOfChildren = availabilitySearchCriteria.NumberOfChildren, UnavailabilityReasonCode = UnavailabilityReasonCode.NoInventory, BusinessCandidates = new List<AvailabilityResultBusiness>() }; }
/// <summary> /// Modify the presented criteria if this check is for a pre-existing booking /// </summary> /// <param name="availabilitySearchCriteria">search Criteria</param> /// <param name="booking">Booking object</param> internal AvailabilitySearchResult UpdateCriteriaForExistingBooking(AvailabilitySearchCriteria availabilitySearchCriteria, Model.Booking.Booking booking) { if (!availabilitySearchCriteria.BusinessIds.Contains(booking.BusinessId)) { return GetNullBusinessAvailabilityResult(availabilitySearchCriteria); } if (booking.Order.IsOTA) { if (DateTime.Today < booking.StartDate.Date) { if (availabilitySearchCriteria.StartDate.ConvertToTimeZoneLessDateTime().Date != booking.StartDate.Date || availabilitySearchCriteria.EndDate.ConvertToTimeZoneLessDateTime().Date != booking.EndDate.Date ) { return GetNullBusinessAvailabilityResult(availabilitySearchCriteria); } } } return null; }
/// <summary> /// Search availability using online business logic /// </summary> /// <param name="onlineAvailabilitySearchCriteria">search criteria to use</param> /// <returns>Available rooms found</returns> public AvailabilitySearchResult CheckOnlineAvailability(Model.Room.Online.AvailabilitySearchCriteria onlineAvailabilitySearchCriteria) { Logger.LogInfo("==========CheckOnlineAvailability Called=========="); Logger.LogDebugAsXml(onlineAvailabilitySearchCriteria); AvailabilitySearchResult searchResults = null; var businessIds = new List<long>(); var currency = onlineAvailabilitySearchCriteria.RequestedCurrency; foreach (var shortName in onlineAvailabilitySearchCriteria.BusinessShortNames) { // will need to send the list of businesses in future CachedBusinessDigest currentBusiness = Cache.Cache.BusinessByShortName.TryGetValue(shortName); if (currentBusiness != null) { businessIds.Add(currentBusiness.Id); if (currency == null || String.IsNullOrEmpty(currency)) { currency = currentBusiness.WorkingCurrencyCode; } } } if (businessIds.Any()) { // Check that is not in the past onlineAvailabilitySearchCriteria.IsValid(); if (onlineAvailabilitySearchCriteria.RoomSearchCriteria == null || onlineAvailabilitySearchCriteria.RoomSearchCriteria.Count == 0) { onlineAvailabilitySearchCriteria.RoomSearchCriteria = new List<Model.Room.Online.RoomRestrictions> { new Model.Room.Online.RoomRestrictions {NumberOfAdults = null, NumberOfChildren = null} }; } Model.Room.Online.RoomRestrictions firstRestriction = onlineAvailabilitySearchCriteria.RoomSearchCriteria[0]; Channel channel = channelDao.GetChannelByShortName(onlineAvailabilitySearchCriteria.ChannelShortName); if (channel == null) { // Exception since this is online search source and channel id is required. return GetNullBusinessAvailabilityResult(onlineAvailabilitySearchCriteria); } // Set up search criteria AvailabilitySearchCriteria searchCriteria = new AvailabilitySearchCriteria { StartDate = onlineAvailabilitySearchCriteria.StartDate, EndDate = onlineAvailabilitySearchCriteria.EndDate, NumberOfAdults = firstRestriction.NumberOfAdults, NumberOfChildren = firstRestriction.NumberOfChildren, BusinessIds = businessIds, ChannelId = channel.Id, RequestedCurrency = currency }; // Do search here searchResults = CheckAvailability(searchCriteria); } else { // No businesses found so return null result for it searchResults = GetNullBusinessAvailabilityResult(onlineAvailabilitySearchCriteria); } var results = FilterSearchResultsForOnlineCheckAvailability(searchResults); Logger.LogInfo("==========CheckOnlineAvailability Returns=========="); Logger.LogDebugAsXml(results); return results; }
/// <summary> /// update availability with the prices from cache /// </summary> /// <param name="searchCriteria">criteria for original search</param> /// <param name="candidateRooms">result of search</param> /// <param name="concurrentRateCacheDict">cache for businesses in search</param> public void UpdateAvailabilityWithRateCache(AvailabilitySearchCriteria searchCriteria, List<RoomsAvailability> candidateRooms, Dictionary<long, List<RateCache>> concurrentRateCacheDict) { var startDate = searchCriteria.StartDate.ConvertToTimeZoneLessDateTime(); var endDate = searchCriteria.EndDate.ConvertToTimeZoneLessDateTime(); var stayLength = endDate.Subtract(startDate).Days; Parallel.ForEach(candidateRooms, availableRoom => { // if already unavailable (occupancy or inventory reason), skip the cache check if (!availableRoom.UnavailabilityReason.HasValue) { List<RateCache> currentCache; if (concurrentRateCacheDict.TryGetValue(availableRoom.BusinessId, out currentCache) && currentCache != null) { // have cache for this business // get distinct prices per day var distinctByDayParticularCache = currentCache.Where(rc => rc.Date >= startDate && rc.Date < endDate && rc.Adults == (searchCriteria.NumberOfAdults.HasValue ? searchCriteria.NumberOfAdults.Value : 1) && rc.Children == (searchCriteria.NumberOfChildren.HasValue ? searchCriteria.NumberOfChildren.Value : 0) && rc.RoomTypeId == availableRoom.RoomTypeId && rc.RatePlanId == availableRoom.RatePlanId).GroupBy(p => p.Date).Select(pp => pp.First()).ToList(); // check 0 minstay for check in day if (distinctByDayParticularCache.Any(rc => rc.MinStay == 0 && rc.Date == startDate)) { // no availability because of no check in availableRoom.UnavailabilityReason = UnavailabilityReasonCode.CheckInNotPossible; } else if ( distinctByDayParticularCache.Any( rc => rc.MinStay > stayLength && rc.Date == startDate)) { // no availability because of minstay length on check in day availableRoom.UnavailabilityReason = UnavailabilityReasonCode.MinStayCriteriaNotMet; } else { // check there are prices for each day if (distinctByDayParticularCache.Count() == stayLength) { availableRoom.TotalRate = distinctByDayParticularCache.Sum(rc => rc.Rate); availableRoom.TotalWasRate = distinctByDayParticularCache.Sum(rc => rc.WasRate); // check for not matching cache to requested currency if (distinctByDayParticularCache.Any(rc => rc.CurrencyCode != searchCriteria.RequestedCurrency)) { DoExchangeRateConversion(availableRoom, distinctByDayParticularCache.First().CurrencyCode, searchCriteria.RequestedCurrency); } // get distinct names for the days availableRoom.DistinctAppliedPromotionNames = distinctByDayParticularCache.GroupBy(r => r.PromoName) .Select(t => t.First().PromoName) .ToList(); } else { // no availability because of lack of prices (only if not already not available) if (!availableRoom.UnavailabilityReason.HasValue) { availableRoom.UnavailabilityReason = UnavailabilityReasonCode.NoRateDefined; } } } } else // no cache for this business, mark as unavailable because of no rates defined { // no availability because of lack of prices (only if not already not available) if (!availableRoom.UnavailabilityReason.HasValue) { availableRoom.UnavailabilityReason = UnavailabilityReasonCode.NoRateDefined; } } } }); }
public void AvailabilityCheckWherePeriodIsLargerThan365DaysValidationException() { // Arrange var criteria = new AvailabilitySearchCriteria { BusinessIds = new List<long>() {BUSINESS_ID}, StartDate = new CalendarDate() { Day = 1, Month = 1, Year = 2030 }, EndDate = new CalendarDate() { Day = 4, Month = 1, Year = 2031 }, NumberOfAdults = 1, NumberOfChildren = 0 }; // Act and Assert CheckForEviivoException<ValidationException>(() => availabilityManager.CheckAvailability(criteria), "Period Longer than 365 days throws Validation Exception", "SRVEX30029"); }
public void CheckIfThereAreNoRoomsNoAvailabilityIsReturned() { // Arrange // Criteria to search for var criteria = new AvailabilitySearchCriteria { ChannelId = 5, BusinessIds = new List<long>() {BUSINESS_ID}, StartDate = new CalendarDate() { Day = 1, Month = 1, Year = 2030 }, EndDate = new CalendarDate() { Day = 5, Month = 1, Year = 2030 }, NumberOfAdults = 2, NumberOfChildren = 0, RequestedCurrency = "GBP" }; CacheHelper.StubBusinessCacheSingleBusiness(BUSINESS_ID); Cache.Business.Invalidate(); var currencyDaoMock = new Mock<IBusinessCurrencyDao>(); currencyDaoMock.Setup(cd => cd.GetCurrencies("root")).Returns(new List<Currency> { new Currency("GBP", "£", "pound", 2), new Currency("USD", "$", "dollar", 2) }); Cache.CurrencyCache.Dao = currencyDaoMock.Object; // Make sure the rooms are quickly determined using a GetAvailabileRoomsFor method pricingAvailabilityDao.Setup(x => x.GetAvailabilityForBusinessesBetweenDates(false, It.Is<AvailabilitySearchCriteria>( y => y.Equals(criteria)))) .Returns(new List<RoomsAvailability>()); // Act var result = availabilityManager.CheckAvailability(criteria); // Assert // Check the basic criteria data was populated to the result Assert.AreEqual(criteria.NumberOfAdults, result.NoOfAdults, "Check that the criteria data has been successfully transferred to the Result"); Assert.AreEqual(criteria.NumberOfChildren, result.NoOfChildren, "Check that the criteria data has been successfully transferred to the Result"); Assert.AreEqual(criteria.StartDate, result.StartDate, "Check that the criteria data has been successfully transferred to the Result"); Assert.AreEqual(criteria.EndDate, result.EndDate, "Check that the criteria data has been successfully transferred to the Result"); // Confirm no availability was returned Assert.IsEmpty(result.BusinessCandidates, "There should not be any businesses with results as none were returned by the stubs"); Assert.IsNotNull(result.UnavailabilityReasonCode, "UnAvailabilityReasonCode is null."); Assert.AreEqual(UnavailabilityReasonCode.NoInventory, result.UnavailabilityReasonCode, "Reason code returned is incorrect."); CacheHelper.ReAssignBusinessDaoToBusinessCache(); }
public void AvailabilityCheckIfLessThanOneAdultIsSpecifiedThrowsValidationException() { // Arrange var criteria = new AvailabilitySearchCriteria { BusinessIds = new List<long>() {BUSINESS_ID}, StartDate = new CalendarDate() { Day = 1, Month = 1, Year = 2030 }, EndDate = new CalendarDate() { Day = 1, Month = 2, Year = 2030 }, NumberOfAdults = 0, NumberOfChildren = 0 }; //Act and Assert CheckForEviivoException<ValidationException>(() => availabilityManager.CheckAvailability(criteria), "Less than one adult throws validation exception", "SRVEX30037"); }
public void CheckNoAvailabilityIfCriteriaDatesDontMatchBookingDates(IntegrationTypeEnum type, DateTime startDate, DateTime criteriaStartDate, DateTime endDate, DateTime criteriaEndDate) { //Arrange var criteria = new AvailabilitySearchCriteria { ModifyBookingId = BOOKING_ID, RatePlanId = CRITERIA_RATE_PLAN_ID, RoomTypeId = CRITERIA_ROOM_TYPE_ID, StartDate = new CalendarDate{ Day = criteriaStartDate.Day, Month = criteriaStartDate.Month, Year = criteriaStartDate.Year}, EndDate = new CalendarDate{ Day = criteriaEndDate.Day, Month = criteriaEndDate.Month, Year = criteriaEndDate.Year}, BusinessIds = new List<long>{ BUSINESS_ID} }; var booking = new Booking { Order = new Order { IntegrationType = type, OrderSourceCode = "D" }, StartDate = startDate, EndDate = endDate, RatePlanId = BOOKING_RATE_PLAN_ID, RoomTypeId = BOOKING_ROOM_TYPE_ID, BusinessId = BUSINESS_ID }; //Act var result = availabilityManager.UpdateCriteriaForExistingBooking(criteria, booking); //Assert Assert.AreNotEqual(null, result, "Availability incorrectly set to available"); Assert.AreEqual(CRITERIA_RATE_PLAN_ID, criteria.RatePlanId, "Rate Plan Id Modified Incorrectly"); Assert.AreEqual(CRITERIA_ROOM_TYPE_ID, criteria.RoomTypeId, "Room Type Modified incorrectly"); }
/// <summary> /// Check Availability for supplied criteria /// </summary> /// <param name="availabilitySearchCriteria">Criteria to consider in availability check</param> /// <param name="existingBooking">booking to be modified (if already loaded)</param> /// <returns>The Availability Result based on the criteria supplied</returns> public virtual AvailabilitySearchResult CheckAvailability(AvailabilitySearchCriteria availabilitySearchCriteria, Model.Booking.Booking existingBooking = null) { Logger.LogInfo("==========CheckAvailability Called=========="); Logger.LogDebugAsXml(availabilitySearchCriteria); AvailabilitySearchResult result = null; if (availabilitySearchCriteria.ModifyBookingId.HasValue) { existingBooking = existingBooking ?? bookingManager.GetByKey(availabilitySearchCriteria.ModifyBookingId.Value); //Modify the presented criteria if this check is for a pre-existing booking result = UpdateCriteriaForExistingBooking(availabilitySearchCriteria, existingBooking); if (result != null) { return result; } } // Validate the criteria availabilitySearchCriteria.IsValid(); // Get the availability, only return available if there is no channel (help performance on pms slightly) bool onlyReturnAvailable = !availabilitySearchCriteria.ChannelId.HasValue; // set up tasks for availability / rate fetch List<RoomsAvailability> candidateRooms = null; // check if requested currency isn't one of the two for each business var criteriaSentToSproc = availabilitySearchCriteria.Clone(); Task availabilityTask = TaskProxy.StartTask( () => candidateRooms = pricingAvailabilityDao.GetAvailabilityForBusinessesBetweenDates(onlyReturnAvailable, criteriaSentToSproc)); // set up concurrent dictionary with capacity = number of businesses Dictionary<long, List<RateCache>> rateCacheDict = null; Task cacheTask = TaskProxy.StartTask(() => rateCacheDict = RateCacheManager.GetRatesByBusinessesAndDateRange (availabilitySearchCriteria.BusinessIds, availabilitySearchCriteria .StartDate.ConvertToTimeZoneLessDateTime(), availabilitySearchCriteria .EndDate.ConvertToTimeZoneLessDateTime())); Task.WaitAll(availabilityTask, cacheTask); // set the currency for the returned candidates // previously done in sproc var currencyCache = Cache.Cache.CurrencyCache.GetValue("root"); var requestedCurrency = currencyCache.Get(availabilitySearchCriteria.RequestedCurrency); string isoCode = availabilitySearchCriteria.RequestedCurrency; if (requestedCurrency != null) { isoCode = requestedCurrency.ISOCode; } foreach (var cR in candidateRooms) { cR.Currency = requestedCurrency; cR.CurrencyCode = isoCode; } // create initial list of businesses with those added that had neither currency List<AvailabilityResultBusiness> availableBusinesses = (from id in availabilitySearchCriteria.BusinessIds where !criteriaSentToSproc.BusinessIds.Contains(id) select new AvailabilityResultBusiness(UnavailabilityReasonCode.MissingCurrency, id)).ToList(); // If there is no rooms return AvailabilitySearchResult as there is no rooms to check for RoomTypes etc if (candidateRooms == null || candidateRooms.Count == 0) { // no availability or bad business, return empty result back var nullBusinessResult = GetNullBusinessAvailabilityResult(availabilitySearchCriteria); // so that if it was because of currency, we send that back nullBusinessResult.BusinessCandidates = availableBusinesses; if (nullBusinessResult.BusinessCandidates.Any(bc => bc.UnavailabilityReasonCode.HasValue)) { nullBusinessResult.UnavailabilityReasonCode = nullBusinessResult.BusinessCandidates.First(bc => bc.UnavailabilityReasonCode.HasValue).UnavailabilityReasonCode; } return nullBusinessResult; } // assign cache and deal with 0 prices / minloss based on cache results UpdateAvailabilityWithRateCache(availabilitySearchCriteria, candidateRooms, rateCacheDict); // set prepay based on rates set from above UpdateAvailabilityWithPrepay(candidateRooms, availabilitySearchCriteria); // If modify booking for an OTA booking then update all the rates with the current booking rate as OTA booking pricing cannot be changed if (availabilitySearchCriteria.ModifyBookingId.HasValue && existingBooking.Order.IsOTA) { // Set all fields on the available room object foreach (var room in candidateRooms) { room.TotalRate = existingBooking.Cost.Value; SetRoomTypeName(room); } } else { candidateRooms.ForEach(SetRoomTypeName); } // Create the object to be returned result = new AvailabilitySearchResult { StartDate = availabilitySearchCriteria.StartDate, EndDate = availabilitySearchCriteria.EndDate, NoOfAdults = availabilitySearchCriteria.NumberOfAdults, NoOfChildren = availabilitySearchCriteria.NumberOfChildren }; // sort the results by business AvailabilityResultBusiness currentBusiness = null; AvailabilityResultRoomType currentRoomType = null; foreach (RoomsAvailability candidate in candidateRooms) { if (currentBusiness == null || candidate.BusinessId != currentBusiness.BusinessId) { // Currently needs update to get all the businesses in list // We also need to check the criteria is valid for the correct time zone of the businesses. All businesses are assumed in the same time zone var business = Cache.Cache.Business.TryGetValue(candidate.BusinessId); if (business == null) { continue; } // for last of previous business AddRoomTypeToBusiness(currentRoomType, currentBusiness, availabilitySearchCriteria); currentRoomType = null; // add old business to list AddBusinessToList(currentBusiness, availableBusinesses); // set up new business var newBusiness = new AvailabilityResultBusiness { BusinessId = candidate.BusinessId, ShortName = business.ShortName, RoomTypes = new List<AvailabilityResultRoomType>(), Is3DSecureAllowed = business.MerchantDetails.Is3DSecureAllowed ?? true, IsAmexAllowed = business.MerchantDetails.IsAmexAllowed ?? true, IsPaypalAllowed = business.MerchantDetails.IsPaypalAllowed ?? false }; currentBusiness = newBusiness; } // add this roomtype candidate to the business if (currentRoomType == null || candidate.RoomTypeId != currentRoomType.RoomTypeId) { // first add the old one if it is present AddRoomTypeToBusiness(currentRoomType, currentBusiness, availabilitySearchCriteria); // set up new room type AvailabilityResultRoomType newRoomType = new AvailabilityResultRoomType { RoomTypeId = candidate.RoomTypeId, BusinessId = candidate.BusinessId, RoomTypeName = candidate.RoomTypeName, RatesAndRoomsAvailable = new List<RoomsAvailability>(), UnAvailabilityReasonCode = null }; currentRoomType = newRoomType; } currentRoomType.RatesAndRoomsAvailable.Add(candidate); } AddRoomTypeToBusiness(currentRoomType, currentBusiness, availabilitySearchCriteria); AddBusinessToList(currentBusiness, availableBusinesses); if (!availableBusinesses.Any()) { // bad business list, return empty result back return GetNullBusinessAvailabilityResult(availabilitySearchCriteria); } result.BusinessCandidates = availableBusinesses; CorrectWasPriceForResults(candidateRooms); Logger.LogInfo("==========CheckAvailability Returns=========="); Logger.LogDebugAsXml(result); return result; }