/// <summary> /// Process Room Type Changes /// </summary> /// <param name="queueItem">Queue Item</param> /// <param name="providerSubscriberOptInLookup">Provider Subscriber Opt In list</param> public bool ProcessChange(IQueueItem queueItem, ref ProviderSubscriberOptInsLookup providerSubscriberOptInLookup) { var roomTypeChange = XmlSerialization.XmlDeserializeFromString<PushRoomTypeUpdate>(queueItem.Payload); var providerId = roomTypeChange.BusinessId.ToGuid(); var roomTypeId = roomTypeChange.RoomTypeId.ToGuid(); RoomTypeChangeMessage roomTypeChangeMessage; RoomTypeChangeType roomTypeChangeType; Enum.TryParse(roomTypeChange.Action, out roomTypeChangeType); switch (roomTypeChangeType) { case RoomTypeChangeType.AddRoomType: roomTypeChangeMessage = new RoomTypeChangeMessage(providerId, roomTypeId, ChangeType.Insert, RoomTypeChangeMessage.RoomTypeChangeType.Full); break; case RoomTypeChangeType.ModifyRoomType: roomTypeChangeMessage = new RoomTypeChangeMessage(providerId, roomTypeId, ChangeType.Update, RoomTypeChangeMessage.RoomTypeChangeType.Attribute); break; case RoomTypeChangeType.DeleteRoomType: roomTypeChangeMessage = new RoomTypeChangeMessage(providerId, roomTypeId, ChangeType.Delete, RoomTypeChangeMessage.RoomTypeChangeType.Full); break; default: return false; } bool isSuccess = true; foreach (var messagingIntegratorService in CreateServices(roomTypeChangeMessage)) { isSuccess &= messagingIntegratorService.ProcessAndQueueChangeUpdates(providerSubscriberOptInLookup, roomTypeChangeMessage); } return isSuccess; }
/// <summary> /// Process Rate Plan Changes /// </summary> /// <param name="queueItem">Queue Item</param> /// <param name="providerSubscriberOptInLookup">Provider Subscriber Opt In list</param> public bool ProcessChange(IQueueItem queueItem, ref ProviderSubscriberOptInsLookup providerSubscriberOptInLookup) { var ratePlanChange = XmlSerialization.XmlDeserializeFromString<PushRatePlanUpdate>(queueItem.Payload); ChangeType changeType; RatePlanChangeType ratePlanChangeType; Enum.TryParse(ratePlanChange.Action, out ratePlanChangeType); switch (ratePlanChangeType) { //adding of a new rate plan will create a new roomtype in the Handle - this is because every RoomType/RatePlan combination is treated as a Product Type in Expedia case RatePlanChangeType.AddRatePlan: changeType = ChangeType.Insert; break; case RatePlanChangeType.ModifyRatePlan: changeType = ChangeType.Update; break; case RatePlanChangeType.DeleteRatePlan: changeType = ChangeType.Delete; break; default: return false; } var ratePlanChangeMessage = new RatePlanChangeMessage(ratePlanChange.BusinessId.ToGuid(), changeType, Helper.GetProductGuid(ratePlanChange.RoomTypeId, ratePlanChange.RatePlanId), ratePlanChange.StartDate, ratePlanChange.EndDate); bool isSuccess = true; foreach (var messagingIntegratorService in CreateServices(ratePlanChangeMessage)) { isSuccess &= messagingIntegratorService.ProcessAndQueueChangeUpdates(providerSubscriberOptInLookup, ratePlanChangeMessage); } return isSuccess; }
/// <summary> /// Add small bit to beginning for this type of execute, otherwise same as base /// </summary> public override void ExecuteTask() { providerSubscriberOptInLookup = providerSubscriberOptInService.Load(); Log.LogInfo("Number of providers that are opted into AIG subscribers are {0}", null, providerSubscriberOptInLookup.GetProviderIdsOptedIntoSubscribers().Count); base.ExecuteTask(); }
/// <summary> /// Process Booking Changes /// </summary> /// <param name="queueItem">Queue Item</param> /// <param name="providerSubscriberOptInLookup">Provider Subscriber Opt In list</param> public bool ProcessChange(IQueueItem queueItem, ref ProviderSubscriberOptInsLookup providerSubscriberOptInLookup) { var inventoryChange = XmlSerialization.XmlDeserializeFromString<PushInventoryUpdate>(queueItem.Payload); ChangeType changeType; InventoryChangeType inventoryChangeType; Enum.TryParse(inventoryChange.Action, out inventoryChangeType); DateTime endDate; switch (inventoryChangeType) { case InventoryChangeType.NewBooking: case InventoryChangeType.NewCloseout: case InventoryChangeType.NewPeriodCloseout: changeType = ChangeType.Insert; break; case InventoryChangeType.CancelBooking: case InventoryChangeType.CancelCloseout: case InventoryChangeType.CancelPeriodCloseout: changeType = ChangeType.Delete; break; default: return false; } DateTime startDate = InventoryChangeMessage.GetValidStartDate(inventoryChange.StartDate); //for the booking/closeout update message to AIG, need to specify the date range that is booked out inclusively. This is not the checkin and checkout dates passed //in as parameters, but the start dates date, and the end date - 1 days date. //eg a 1 day booking for 12/09/2008 should have start date 12/09/2008 and end date 12/09/2008 instead of an end date 13/09/2008 //this does not apply to Period Closeouts as the dates are already sent through inclusively if (inventoryChangeType != InventoryChangeType.NewPeriodCloseout && inventoryChangeType != InventoryChangeType.CancelPeriodCloseout) { endDate = InventoryChangeMessage.GetValidEndDate(inventoryChange.StartDate, inventoryChange.EndDate); } else { endDate = inventoryChange.EndDate; } var inventoryChangeMessage = InventoryChangeMessage.IsValidDate(endDate) ? new InventoryChangeMessage(inventoryChange.BusinessId.ToGuid(), changeType, inventoryChange.RoomId.ToGuid(ROOM_PREFIX), startDate, endDate, inventoryChange.RoomTypeId) : null; if (inventoryChangeMessage == null) { return false; } bool isSuccess = true; foreach (var messagingIntegratorService in CreateServices(inventoryChangeMessage)) { isSuccess &= messagingIntegratorService.ProcessAndQueueChangeUpdates(providerSubscriberOptInLookup, inventoryChangeMessage); } return isSuccess; }
/// <summary> /// Process Room Changes /// </summary> /// <param name="queueItem">Queue Item</param> /// <param name="providerSubscriberOptInLookup">Provider Subscriber Opt In list</param> public bool ProcessChange(IQueueItem queueItem, ref ProviderSubscriberOptInsLookup providerSubscriberOptInLookup) { var roomChange = XmlSerialization.XmlDeserializeFromString<PushRoomUpdate>(queueItem.Payload); ChangeType changeType; RoomChangeType roomChangeType; Enum.TryParse(roomChange.Action, out roomChangeType); //all these actions trigger Handle with a RoomTypeConfigurationUpdate message but i think its still valid to differentiate them in case we need it in the future switch (roomChangeType) { case RoomChangeType.AddRoom: changeType = ChangeType.Insert; break; case RoomChangeType.ModifyRoom: //if we cant view the room online or it is not active then remove it if (!roomChange.IsAvailableOnline || !roomChange.IsActive) { changeType = ChangeType.Delete; } else { changeType = ChangeType.Update; } break; case RoomChangeType.DeleteRoom: changeType = ChangeType.Delete; break; default: return false; } var roomChangeMessage = new RoomChangeMessage(roomChange.BusinessId.ToGuid(), changeType, roomChange.RoomTypeId.ToGuid(ROOM_TYPE_PREFIX), roomChange.RoomId.ToGuid(ROOM_PREFIX)); bool isSuccess = true; foreach (var messagingIntegratorService in CreateServices(roomChangeMessage)) { isSuccess &= messagingIntegratorService.ProcessAndQueueChangeUpdates(providerSubscriberOptInLookup, roomChangeMessage); } return isSuccess; }
/// <summary> /// This method will process an availablitiy update item and convert it into an PPC message and add it to the queue. /// </summary> /// <param name="providerSubscriberOptinLookup">ProviderSubscriberOptInsLookup</param> /// <param name="changeMessage">BaseChangeMessage</param> /// <returns>Return always True</returns> public bool ProcessAndQueueChangeUpdates(ProviderSubscriberOptInsLookup providerSubscriberOptinLookup, BaseChangeMessage changeMessage) { try { IMessageHandler messageHandler = MessageHandlerFactory.CreateMessageHandler(); if (messageHandler != null) { messageHandler.Handle(changeMessage); } } //We must not disturb the overall process (AIG) catch (Exception ex) { Logger.LogFatal("Error in PPCIntegratorServices :", null, ex); } return true; }
/// <summary> /// This method will call the base handler methods depending on the type of availbility update item. /// </summary> /// <param name="providerAndSubscriberOptInLookup">List of providers opted into AIG</param> /// <param name="baseChangeMessage">Availability update item to process</param> /// <returns>True is successful otherwise False</returns> private bool HandleChangeMessage(ProviderSubscriberOptInsLookup providerAndSubscriberOptInLookup, BaseChangeMessage baseChangeMessage) { //get the AIGSubscriberByOptinPriceTypeList list now or null. it could be null in a case //where it is a provider opt out and the list has been refreshed. var subscriberByOptinList = (providerAndSubscriberOptInLookup == null) ? null : providerAndSubscriberOptInLookup.GetSubscribersByProviderId(baseChangeMessage.ProviderId); if (subscriberByOptinList == null) { return true; } try { var inventoryChangeMessage = baseChangeMessage as InventoryChangeMessage; if (inventoryChangeMessage != null) { return HandleInventoryUpdate(subscriberByOptinList, inventoryChangeMessage); } var providerChangeMessage = baseChangeMessage as ProviderChangeMessage; if (providerChangeMessage != null) { return HandleProviderUpdate(subscriberByOptinList, providerChangeMessage); } var ratePlanChangeMessage = baseChangeMessage as RatePlanChangeMessage; if (ratePlanChangeMessage != null) { return HandleRatePlanUpdate(subscriberByOptinList, ratePlanChangeMessage); } var roomTypeChangeMessage = baseChangeMessage as RoomTypeChangeMessage; if (roomTypeChangeMessage != null) { return HandleRoomTypeUpdate(subscriberByOptinList, roomTypeChangeMessage); } var roomChangeMessage = baseChangeMessage as RoomChangeMessage; if (roomChangeMessage != null) { return HandleRoomUpdate(subscriberByOptinList, roomChangeMessage); } return true; } catch (Exception ex) { //this is a catch all if anything goes wrong during the data retrieval part Logger.ErrorFormat("Error occured while processing {0} {1}", baseChangeMessage, ex); var providerErrorMessage = ProviderError.CreateProviderError(baseChangeMessage.SubscriberId.ToString(), baseChangeMessage.ProviderId.ToString(), "Unhandled exception during procesing: " + ex.Message); return QueueMessage(providerErrorMessage); } }
/// <summary> /// This method will check to confirm that an update is required for this change message /// </summary> /// <param name="providerAndSubscriberOptInLookup">List of providers opted in to AIG</param> /// <param name="baseChangeMessage">Base change message to check</param> /// <returns>True if successful otherwise False</returns> private static bool IsChangeMessageRequiredUpdate(ProviderSubscriberOptInsLookup providerAndSubscriberOptInLookup, BaseChangeMessage baseChangeMessage) { if (providerAndSubscriberOptInLookup.ContainsProvider(baseChangeMessage.ProviderId)) { var subscriberByOptinList = providerAndSubscriberOptInLookup.GetSubscribersByProviderId(baseChangeMessage.ProviderId); if (subscriberByOptinList == null) { return false; } //updates involving a businessaccount being activated/deactivated will not contain a distributor id if (baseChangeMessage.SubscriberId == Guid.Empty) { return true; } if (subscriberByOptinList.ContainsSubscriber(baseChangeMessage.SubscriberId)) { return true; } } return false; }
/// <summary> /// This method will process an availablitiy update item and convert it into an AIG message and add it to the queue. It will however, not commit this message /// till the CommmitUpdates method is called. /// </summary> /// <param name="providerSubscriberOptinLookup">List of providers opted in to AIG</param> /// <param name="changeMessage">Change message to process</param> /// <returns>True if successful otherwise False</returns> public bool ProcessAndQueueChangeUpdates(ProviderSubscriberOptInsLookup providerSubscriberOptinLookup, BaseChangeMessage changeMessage) { var isSuccesful = true; var providerId = changeMessage.ProviderId; using (var transactionScope = new TransactionScope(currentTransactionScope, queryTransactionOptions)) { Logger.InfoFormat("Processing update for Business: {0}", providerId); if (IsChangeMessageRequiredUpdate(providerSubscriberOptinLookup, changeMessage)) { isSuccesful = HandleChangeMessage(providerSubscriberOptinLookup.GetProviderIdsOptedIntoSubscribers().Contains(changeMessage.ProviderId) ? providerSubscriberOptinLookup : null, changeMessage); } else { //It will reach here is the update is for a provider not in aig subscriber list Logger.Debug(string.Format("Business {0} with change message type {1} was not processed as distributor {2} is not an AIG subscriber OR the provider is not opted in", changeMessage.ProviderId, changeMessage.GetType(), changeMessage.SubscriberId)); } Logger.InfoFormat("SUCCESSFULLY completed processing updates for Business: {0}", providerId); transactionScope.Complete(); } return isSuccesful; }
/// <summary> /// Process the change for a provider /// </summary> /// <param name="queueItem">queue item with push provider payload to process</param> /// <param name="providerSubscriberOptInLookup">for loading and reloading</param> /// <returns>true if successful</returns> public bool ProcessChange(IQueueItem queueItem, ref ProviderSubscriberOptInsLookup providerSubscriberOptInLookup) { var providerChange = XmlSerialization.XmlDeserializeFromString<PushProviderUpdate>(queueItem.Payload); var providerId = providerChange.BusinessId.ToGuid(); var reloadOptinsBefore = false; var reloadOptinsAfter = false; ProviderChangeType providerChangeType; Enum.TryParse(providerChange.Action, out providerChangeType); ProviderChangeMessage providerChangeMessage = null; switch (providerChangeType) { case ProviderChangeType.ChannelOptIn: reloadOptinsBefore = true; //if the provider is opting into expedia then create a insert message providerChangeMessage = ProviderChangeMessage.CreateProviderInsertMessage(providerId, providerChange.ChannelGuid); break; case ProviderChangeType.ChannelOptOut: reloadOptinsAfter = true; //if the provider is opting out of expedia then create a remove message providerChangeMessage = ProviderChangeMessage.CreateProviderRemoveMessage(providerId, providerChange.ChannelGuid); break; case ProviderChangeType.StatusChange: if (providerChange.IsOptinActive) { //if optin flag is true and the provider is actively opted into expedia then create a full update message otherwise an insert message if (providerSubscriberOptInLookup.ContainsProvider(providerId)) { providerChangeMessage = ProviderChangeMessage.CreateProviderFullUpdateMessage(providerId); } else { reloadOptinsBefore = true; providerChangeMessage = ProviderChangeMessage.CreateProviderInsertMessage(providerId, providerChange.ChannelGuid); } } else { //create a delete message if status has changed and optin flag is false providerChangeMessage = ProviderChangeMessage.CreateProviderDeleteMessage(providerId); reloadOptinsAfter = true; } break; case ProviderChangeType.AvailabilityReset: { if (providerChange.IsOptinActive) { providerChangeMessage = ProviderChangeMessage.CreateProviderAvailabilityResetUpdateMessage(providerId, providerChange.ChannelGuid); } break; } case ProviderChangeType.ProviderReset: { if (providerChange.IsOptinActive) { providerChangeMessage = ProviderChangeMessage.CreateProviderResetUpdateMessage(providerId, providerChange.ChannelGuid); } break; } case ProviderChangeType.AttributeChange: { providerChangeMessage = ProviderChangeMessage.CreateProviderAttributeUpdateMessage(providerId, Guid.Empty); break; } default: return false; } //we need to do this before for new optins so the provider/subscriber is in the list otherwise the message wont be processed if (reloadOptinsBefore) { providerSubscriberOptInLookup = providerSubscriberOptInService.Load(); } //send the provider change message to the queue if (providerChangeMessage == null) { return false; } bool isSuccess = true; foreach (var messagingIntegratorService in CreateServices(providerChangeMessage)) { isSuccess &= messagingIntegratorService.ProcessAndQueueChangeUpdates(providerSubscriberOptInLookup, providerChangeMessage); } //we need to do this after so the provider/subscriber is only removed once the message has been sent if (reloadOptinsAfter) { providerSubscriberOptInLookup = providerSubscriberOptInService.Load(); } return isSuccess; }