/// <summary> /// Search availability and then allocate the shared rooms between the guests /// to avoid overbooking /// </summary> /// <param name="criteria">Search availability criteria</param> /// <returns>A list of availability results indexed by room restriction</returns> private ConcurrentDictionary<RoomRestrictions, AvailabilitySearchResult> SearchAvailabilityAndAllocateRooms(AvailabilitySearchCriteria criteria) { var availabilitySearchResults = new ConcurrentDictionary<RoomRestrictions, AvailabilitySearchResult>(); //we sort to allocate the biggest criteria first var sortedRoomCriteria = criteria.RoomSearchCriteria.OrderByDescending(r => r.NumberOfAdults + r.NumberOfChildren); //Need to clone AvailabilitySearchCriteria Parallel.ForEach(sortedRoomCriteria, roomCriteria => { var localCriteria = (Model.Room.Online.AvailabilitySearchCriteria) criteria.Clone(); localCriteria.RoomSearchCriteria = new List<RoomRestrictions> {roomCriteria}; availabilitySearchResults.TryAdd(roomCriteria, availabilityManager. CheckOnlineAvailability( localCriteria)); }); var sharedRooms = GetSharedRooms(sortedRoomCriteria, availabilitySearchResults); SplitSharedRoomsByResultSet(sharedRooms, sortedRoomCriteria, availabilitySearchResults); var businessWithNoAvailability = new Dictionary<long, long>(); //we allocate the biggest criteria first foreach (var roomCriteria in sortedRoomCriteria) { var availabilitySearchResult = availabilitySearchResults[roomCriteria]; var allocatedBusinessCandidates = new List<AvailabilityResultBusiness>(); foreach (var businessCandidate in availabilitySearchResult.BusinessCandidates) { var roomsAvailabilityResultRoomType = new List<AvailabilityResultRoomType>(); foreach (var roomType in businessCandidate.RoomTypes) { FindFirstAvailableRoomsInRoomType(roomType, roomsAvailabilityResultRoomType); } businessCandidate.RoomTypes = roomsAvailabilityResultRoomType; if (!roomsAvailabilityResultRoomType.Any() && !businessWithNoAvailability.ContainsKey(businessCandidate.BusinessId)) { businessCandidate.UnavailabilityReasonCode = UnavailabilityReasonCode.NoInventory; businessWithNoAvailability.Add(businessCandidate.BusinessId, businessCandidate.BusinessId); } allocatedBusinessCandidates.Add(businessCandidate); } availabilitySearchResult.BusinessCandidates = allocatedBusinessCandidates; if (!allocatedBusinessCandidates.Any()) { availabilitySearchResult.UnavailabilityReasonCode = UnavailabilityReasonCode.NoInventory; } } RemoveBusinessWithPartialAvailability(availabilitySearchResults, businessWithNoAvailability); return availabilitySearchResults; }
private static List<OnlineAvailabilitySearchResultDto> ConvertToDto(AvailabilitySearchCriteria criteria, ConcurrentDictionary<RoomRestrictions, AvailabilitySearchResult> availabilitySearchResults) { var onlineSearchResults = new List<OnlineAvailabilitySearchResultDto>(); foreach (var roomSearchCriteria in criteria.RoomSearchCriteria) { var availabilitySearchResult = availabilitySearchResults[roomSearchCriteria]; // Convert the result back to DTO onlineSearchResults.Add( DataTransferObjectsConverter.ConvertAvailabilitySearchResultToOnlineDto(availabilitySearchResult)); } return onlineSearchResults; }