public Guid OrderTicket(Contracts.Order newOrder, SeatIndex[] seats)
        {
            //1. validate the order is valid
            //validate newOrder.EventInfo and newOrder.CustomerInfo
            ICrmBase crmProx = null;
            IShowsService showsProx = null;
            IPricingService pricingProx = null;
            IReservationService reservationsProx = null;
            Guid reservationID;

            if (newOrder == null)
                throw new NullReferenceException(StringsResource.NullOrder);
            if (newOrder.CustomerInfo == null)
                throw new NullReferenceException(StringsResource.NullCustomer);
            if (newOrder.EventInfo == null)
                throw new NullReferenceException(StringsResource.NullEvent);
            if ((seats == null) || (seats.Count() == 0))
                throw new ArgumentException(StringsResource.NoSeatsInOrder);

            #region Validate Customer
            //Contact the Crm service to ensure the customer exist.
            lock (this)
            {
                if (crmChf == null)
                    crmChf = new ChannelFactory<ICrmBase>("CrmCertEP");
            }

            try
            {
                crmProx = crmChf.CreateChannel();
                var customer = crmProx.GetCustomerByID(newOrder.CustomerInfo.ID);
                if (customer == null)
                    throw new TicketingException(string.Format(StringsResource.CustomerNotFound, newOrder.CustomerInfo.ID));
                newOrder.CustomerInfo = CustomerMapper.MapToTicketingCustomer(customer);

            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new TicketingException(StringsResource.FailedToContactCrm, ex);
            }
            finally
            {
                var channel = crmProx as ICommunicationObject;
                if ((channel != null) && (channel.State == CommunicationState.Opened))
                    channel.Close();
            }

            #endregion

            #region Validate Event

            ShowsService.Contracts.Event _event;

            //1. contact the shows service to fetch information about the event.
            lock (this)
            {
                if (showsChf == null)
                    showsChf = new ChannelFactory<IShowsService>("ShowEP");
            }

            try
            {
                showsProx = showsChf.CreateChannel();
                _event = showsProx.FindEventByID(newOrder.EventInfo.EventID);
                if (_event == null)
                    throw new TicketingException(string.Format(StringsResource.EventNotFound, newOrder.EventInfo.EventID));
                newOrder.EventInfo = _event;
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new TicketingException(StringsResource.FailedToContactShows + " " + ex.Message, ex);
            }
            finally
            {
                var channel = showsProx as ICommunicationObject;
                if ((channel != null) && (channel.State == CommunicationState.Opened))
                    channel.Close();
            }

            //2. check the event exist and it is open
            if ((_event == null) || (_event.State != EventState.Opened))
                throw new TicketingException(StringsResource.InvalidOrClosedEvent);
            #endregion

            #region Call Pricing to calculate the total price
            lock (this)
            {
                if (pricingChf == null)
                    pricingChf = new ChannelFactory<IPricingService>("PricingEP");
            }

            try
            {
                pricingProx = pricingChf.CreateChannel();
                var price = pricingProx.CalculatePrice(reductionCode: newOrder.CustomerInfo.ReductionCode.Value,
                                                            policyName: newOrder.EventInfo.PricingPolicy,
                                                            listPrice: (int)newOrder.EventInfo.ListPrice,
                                                            numberOfTickets: seats.Count(), currency: null);
                newOrder.TotalPrice = price * seats.Count();

            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new TicketingException(StringsResource.FailedToContactPricing + " " + ex.Message, ex);
            }
            finally
            {
                var channel = pricingProx as ICommunicationObject;
                if ((channel != null) && (channel.State == CommunicationState.Opened))
                    channel.Close();
            }
            #endregion

            #region Call the resrevation service and reserve seats
            //Contact the HallState service to perform the reservation.
            lock (this)
            {
                if (reservationsChf == null)
                    reservationsChf = new ChannelFactory<IReservationService>("ReservationsEP");
            }

            try
            {
                reservationsProx = reservationsChf.CreateChannel();
                reservationID = reservationsProx.CreateResevation(new Reservation()
                {
                    ID = Guid.NewGuid(),
                    CustomerID = newOrder.CustomerInfo.ID,
                    EventID = newOrder.EventInfo.EventID,
                    Seats = seats.ToList(),
                    Remarks = newOrder.Remarks
                });

            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new TicketingException(StringsResource.FailedToContactHallState + " " + ex.Message, ex);
            }
            finally
            {
                var channel = reservationsProx as ICommunicationObject;
                if ((channel != null) && (channel.State == CommunicationState.Opened))
                    channel.Close();
            }

            #endregion


            newOrder.ID = reservationID;
            newOrder.State = OrderState.Created;
            manager.OrderTicket(newOrder);

            #region ClientNotifications
            //ClientNotifications
            string userName = string.Empty;
            if ((OperationContext.Current != null) && (OperationContext.Current.ServiceSecurityContext != null) && (OperationContext.Current.ServiceSecurityContext.PrimaryIdentity != null))
                userName = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;

            var clientRegistrations = MemoryRepository.Current.GetRegistrations(NotificationTypes.TicketingNotification, userName);
            if (clientRegistrations.Length > 0)
                ClientNotificationsManager.SendNotifications(new OrderMessage()
                {
                    Content = "Order Created",
                    OrderID = reservationID
                }, clientRegistrations);

            #endregion

            return newOrder.ID;
        }