public static void CreateTransaction(BookingDto booking, decimal amount, bool minimumCharge, IServices Services)
        {
            try
            {
                UserDto user = Services.Users.GetUserById(booking.Customer.Id);
                if (user != null)
                {
                    InvoiceDto consultationInvoice;

                    switch (user.PaymentMethod)
                    {
                        case PaymentMethod.CreditCard:
                            PaymentResult result = new PaymentResult();
                            if (amount != 0)
                            {
                                result = Services.Payment.Transaction(user.Id.ToString(), amount);

                                if (result.Success)
                                {
                                    consultationInvoice = Services.Invoices.CreateConsultationInvoice(amount, booking.Id, minimumCharge, true, result.Transaction.Id);
                                }
                                else
                                {
                                    Log.Error("Transaction fail. Message: " + result.ErrorMessage + " UserId: " + user.Id);
                                    CreateUnsuccessInvoice(user, booking, Services, amount);
                                }
                            }
                            break;

                        case PaymentMethod.PrePayment:
                            user.PrePaymentAmount -= amount;

                            if (Services.Users.UpdateUserInfo(user))
                            {
                                consultationInvoice = Services.Invoices.CreateConsultationInvoice(amount, booking.Id, minimumCharge, true, null);
                            }
                            else
                            {
                                CreateUnsuccessInvoice(user, booking, Services, amount);
                            }
                            break;

                        default:
                            break;
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("Create new transaction with UserId: " + booking.Customer.Id + " BookingId: " + booking.Id, e);
            }
        }
        private static void CreateUnsuccessInvoice(UserDto user, BookingDto booking, IServices Services, decimal amount)
        {
            ConsultationType consultType;

            switch (booking.Type)
            {
                case BookingType.ASAP:
                    consultType = ConsultationType.StandardHour;
                    break;

                default:
                    Enum.TryParse(booking.Type.ToString(), out consultType);
                    break;
            }
            var call = Services.Call.GetByBookingId(booking.Id);

            InvoiceDto unsuccessInvoice = new InvoiceDto()
            {
                Amount = amount,
                CreatedDate = DateTime.UtcNow,
                ModifiedDate = DateTime.UtcNow,
                Type = InvoiceType.Consultation,
                PaymentStatus = false,
                InvoiceNumber = Services.Invoices.GetInvoiceNumber(),
                Booking = Services.Booking.GetById(booking.Id),
                User = user,
                Description = InvoiceType.Consultation.ToString(),
                RatePerMinute = booking.CostPerMinute,
                ConsultationType = consultType,
            };
            if (call != null)
            {
                unsuccessInvoice.Duration = 0;
            }

            Services.Invoices.Create(unsuccessInvoice);
        }
        ///// <summary>
        ///// General to load Booking By Id
        ///// </summary>
        ///// <param name="bookingId"></param>
        ///// <returns></returns>
        public static PopupConfirmListBookingViewModel LoadBookingByBookingId(
            BookingDto booking, bool isSpecialist)
        {
            //DOTO: TRI
            //// Convert to client time
            //if (!string.IsNullOrEmpty(defaultTimeZoneId)
            //    && booking.StartTime.HasValue
            //    && booking.EndTime.HasValue)
            //{
            //    //booking.StartTime = booking.StartTime.Value.ConvertToClientTimeById(defaultTimeZoneId);
            //    //booking.EndTime = booking.EndTime.Value.ConvertToClientTimeById(defaultTimeZoneId);
            //}

            PopupConfirmListBookingViewModel popupModel = new PopupConfirmListBookingViewModel();
            popupModel = Mapper.Map<BookingDto, PopupConfirmListBookingViewModel>(booking);
            popupModel.ProposedTime = BookingHelper.GetDisplayTime(popupModel.Type, popupModel.Status, popupModel.StartTime,
                popupModel.EndTime);
            var s3Root = BlueChilli.Web.Helpers.S3PathWithoutQuery("").Substring(1);
            popupModel.Avatar = string.Empty;

            string avatar = booking.Specialist.Avatar;
            popupModel.Name = booking.Specialist.Name;
            if (isSpecialist)
            {
                popupModel.Name = booking.Customer.Name;
                avatar = booking.Customer.Avatar;
            }
            if (!string.IsNullOrWhiteSpace(avatar))
            {
                popupModel.Avatar = Path.Combine(s3Root, avatar);
            }

            //if (!string.IsNullOrWhiteSpace(booking.DocumentPath))
            //{
            //    popupModel.DocumentPath = Path.Combine(s3Root, booking.DocumentPath);
            //}
            return popupModel;
        }
        /// <summary>
        /// Get notice after customer click confirm defer
        /// </summary>
        /// <param name="booking"></param>
        /// <param name="isDefer"></param>
        /// <returns></returns>
        public static BookingConfirmDefer GetNotifyAfterConfirmDefer(BookingDto booking, bool isDefer)
        {
            // Check value start time >> If reschedule then start time is unknown
            var _startTime = booking.StartTime.Value.ToShortTimeString();

            if (!isDefer)
            {
                _startTime = Constants.DetermineContent.ToLower();
            }

            var bookingConfirmDefer = new BookingConfirmDefer
            {
                BookingId = booking.Id,
                DeferMinuted = booking.Deferral,
                DateReSchedule = booking.StartTime.Value.ToString(Constants.GlobalDateFormat),
                StartTime = _startTime,
                EndTime = Constants.DetermineContent.ToLower(),
            };
            return bookingConfirmDefer;
        }
        public BookingApi GetBookingInfo(BookingInfo model)
        {
            List<InvoiceDto> invoices = Services.Invoices.GetInvoiceByBookingId(model.BookingId);
            InvoiceDto customerInvoice = new InvoiceDto();
            InvoiceDto specialistInvoice = new InvoiceDto();
            BookingDto booking = new BookingDto();

            if (invoices == null || !invoices.Any())
            {
                booking = Services.Booking.GetById(model.BookingId);
            }
            else
            {
                booking = invoices.First(i => i.Booking.Id == model.BookingId).Booking;
                customerInvoice = invoices.First(i => i.User.Id == booking.Customer.Id && i.Type == InvoiceType.Consultation);
                specialistInvoice = invoices.First(i => i.User.Id == booking.Specialist.Id);
            }

            var bookingInfo = Mapper.Map<BookingApi>(booking);

            bookingInfo.IsMinCharge = false;

            if (bookingInfo != null)
            {
                var call = Services.Call.GetByBookingIdAndConference(bookingInfo.Id);

                var specialist = booking.Specialist;
                var customer = booking.Customer;

                var s3Root = BlueChilli.Web.Helpers.S3PathWithoutQuery("").Substring(1);
                if (!string.IsNullOrWhiteSpace(bookingInfo.DocumentPath))
                {
                    bookingInfo.DocumentPath = Path.Combine(s3Root, bookingInfo.DocumentPath);
                }

                bookingInfo.IsFavourite = Services.Users.IsFavourite(specialist.Id, customer.Id);
                bookingInfo.SpecialistStatus = specialist.CurrentAvailabilityStatus;

                //check specilist is calling with customer to change curremt status to "not avaiable"
                if (!AvailabilityStatus.NotAvailable.Equals(bookingInfo.SpecialistStatus)
                    && Services.Call.CheckCallInProgressBySpecialistId(specialist.Id))
                {
                    bookingInfo.SpecialistStatus = AvailabilityStatus.NotAvailable;
                }

                // Convert to client time
                //TRI:TODO
                //bookingInfo.StartTime = Utilities.ConvertToClientTimeById(bookingInfo.CreatedDate, timeZoneId);
                //bookingInfo.EndTime = Utilities.ConvertToClientTimeById(bookingInfo.EndTime, timeZoneId);
                //bookingInfo.CreatedDate = Utilities.ConvertToClientTimeById(bookingInfo.CreatedDate, timeZoneId);

                if (call != null)
                {
                    if (specialist != null && customer != null)
                    {
                        bookingInfo.IsFeedback = Services.Call.CheckExistFeedbackAndRatingByCallId(call.Id);
                        string recordUrl = "";
                        if (!string.IsNullOrWhiteSpace(call.RecordSid))
                        {
                            var twilioServer = System.Configuration.ConfigurationManager.AppSettings["Twilio_ApiServer"];

                            recordUrl = !string.IsNullOrWhiteSpace(call.RecordUrl) && call.RecordUrl.Contains(twilioServer)
                                    ? Utilities.ConvertLinkRecord(call.RecordSid)
                                    : S3ReaderHelper.CombineFileS3Root(call.RecordUrl);
                        }

                        bookingInfo.Rating = (int)Math.Round(Services.Booking.GetRatingByBooking(bookingInfo.Id), 0, MidpointRounding.AwayFromZero);
                        bookingInfo.PastBooking = new PastBooking();
                        bookingInfo.PastBooking.CallId = call.Id;
                        bookingInfo.PastBooking.DurationMinute = call.Duration;
                        bookingInfo.PastBooking.CallStartTime = call.StartTime.HasValue ? (DateTime?)call.StartTime.Value.ConvertToCurrentTimeZone() : null;
                        bookingInfo.PastBooking.CallEndTime = call.EndTime.HasValue ? (DateTime?)call.EndTime.Value.ConvertToCurrentTimeZone() : null;
                        bookingInfo.PastBooking.RecordUrl = recordUrl;
                        bookingInfo.Feedback = call.Feedback;
                    }
                }

                if (customerInvoice != null && specialistInvoice != null)
                {
                    if (bookingInfo.PastBooking == null)
                    {
                        bookingInfo.PastBooking = new PastBooking();
                    }

                    if (ConsultationType.MinimumCharge.Equals(customerInvoice.ConsultationType))
                    {
                        bookingInfo.IsMinCharge = true;
                    }
                    bookingInfo.IsWaiveFee = customerInvoice.IsWaiveFee;
                    bookingInfo.InvoiceCreatedDate = customerInvoice.CreatedDate.ConvertToCurrentTimeZone();
                    bookingInfo.PastBooking.CustomerTotalRate = customerInvoice.Amount;
                    bookingInfo.PastBooking.SpecialistTotalRate = specialistInvoice.Amount;
                }
            }

            return bookingInfo;
        }
        public InvoiceDto CreateTranscriptionInvoice(decimal amount, int duration, decimal ratePerMinute, BookingDto booking, UserDto user, string transactionId)
        {
            Invoice invoice = new Invoice
            {
                InvoiceNumber = GetInvoiceNumber(),
                Amount = amount,
                GST = SubtractGSTCalculator(amount),
                RatePerMinute = ratePerMinute,
                Duration = duration,
                Type = InvoiceType.OrderTranscript,
                CreatedDate = DateTime.UtcNow,
                ModifiedDate = DateTime.UtcNow,
                SentDate = DateTime.UtcNow,
                User = user.ExposedAs<User>(Repository),
                Currency = Currency.AUD.ToString(),
                PaymentStatus = true,
                Booking = booking.ExposedAs<Booking>(Repository)
            };
            invoice.Description = string.Format(InvoiceConst.InvoiceCallRecordDescription, invoice.Booking.ReferenceNo);
            Repository.Insert<Invoice>(invoice);
            UnitOfWork.Save();

            if (!invoice.Id.Equals(Guid.Empty))
            {
                var mailContent = GetEmailContentOfInvoice(invoice.ExposedAs<InvoiceDto>());
                var mailPdfContent = TranformToInvoiceTemplate(user, invoice.ExposedAs<InvoiceDto>(),
                    null, ConstEmailTemplateKey.ConsultationInvoiceTemplate, null);
                System.Threading.Tasks.Task.Factory.StartNew(() =>
                {
                    byte[] pdfAsByte = HtmlToPdf.GetPdfData(mailPdfContent, baseUrl);

                    string fileName = GenerateInvoiceName(invoice.InvoiceNumber);

                    SendInvoice(fileName, pdfAsByte, mailContent, user.Email, ConstEmailSubject.TranscriptionInvoice);
                });
            }
            else
            {
                throw new ArgumentException("Cannot save transcription invoice to database");
            }

            return invoice.ExposedAs<InvoiceDto>();
        }
        public void GetByBookingAndShortDescription_UsingBookingIdAndShortDescription()
        {
            var settingsMock = new Mock<ISettings>();
            var repositoryMock = new Mock<IRepository>();
            var uowMock = new Mock<IUnitOfWork>();
            var serviceLocatorMock = new Mock<IServiceLocator>();
            serviceLocatorMock.Setup(r => r.GetInstance<IRepository>())
                .Returns(repositoryMock.Object);

            ServiceLocator.SetLocatorProvider(() => serviceLocatorMock.Object);

            // Arrange data
            string description = "Test description";
            Guid id = Guid.NewGuid();
            BookingDto bookingDto = new BookingDto
            {
                Id = id
            };
            Booking booking = new Booking
            {
                Id = id
            };

            BookingEvent bookingEvent = new BookingEvent
            {
                Id = id,
                Booking = booking,
                ShortDescription = description
            };

            List<BookingDto> listBookingDto = new List<BookingDto>();
            listBookingDto.Add(bookingDto);
            List<string> descriptions = new List<string>();
            descriptions.Add(description);

            BookingEvent[] bookingEvents = new BookingEvent[] { bookingEvent };
            repositoryMock.Setup(r => r.Query<BookingEvent>()).Returns(bookingEvents.AsQueryable());
            List<BookingEventDto> bookingEventDtos = new List<BookingEventDto>();

            // Act
            var bookingService = new BookingService(uowMock.Object, repositoryMock.Object, settingsMock.Object);
            bookingEventDtos = bookingService
                .GetByBookingAndShortDescription(listBookingDto, descriptions);

            // Assert
            repositoryMock.Verify(r => r.Query<BookingEvent>());
            Assert.AreEqual(id, bookingEventDtos[0].Id);
        }
        public void Update_BookingDto_BookingDto()
        {
            var settingsMock = new Mock<ISettings>();
            var repositoryMock = new Mock<IRepository>();
            var uowMock = new Mock<IUnitOfWork>();
            var serviceLocatorMock = new Mock<IServiceLocator>();
            serviceLocatorMock.Setup(x => x.GetInstance<IRepository>())
                .Returns(repositoryMock.Object);
            serviceLocatorMock.Setup(x => x.GetInstance<IUnitOfWork>())
                .Returns(uowMock.Object);

            ServiceLocator.SetLocatorProvider(() => serviceLocatorMock.Object);
            repositoryMock.Setup(r => r.CreateUnitOfWork()).Returns(uowMock.Object);

            Guid id = Guid.NewGuid();
            BookingDto bookingDto = new BookingDto
            {
                Id = id
            };

            // Act
            var bookingService = new BookingService(uowMock.Object, repositoryMock.Object, settingsMock.Object);
            bookingService.Update(bookingDto);

            // Assert
            repositoryMock.Verify(repo => repo
                .Update<Booking>(It.Is<Booking>(b => b.Id == bookingDto.Id)));
            uowMock.Verify(uow => uow.Save());
        }
        public IHttpActionResult TalkNow(TalkNowApi model)
        {
            var twiMLUrl = string.Empty;
            bool status = false;
            var booking = new BookingDto();

            try
            {
                // Get Customer and Specialist
                var customer = Services.Users.GetUserById(model.CustomerId);
                var specialist = Services.Users.GetUserById(model.SpecialistId);
                var customerPricing = Services.Booking.GetCustomerPricing(specialist.Profile.Specializations.FirstOrDefault().Id);

                var minimumBookingTime = (int)Services.SystemConfig.GetValueByKey(ParamatricBusinessRules.MINIMUM_BOOKING.ToString());
                var minimumCost = minimumBookingTime * customerPricing.TalkNow;
                var limitAmount = customerPricing.IsApplyNoMinimumCharge ?
                         minimumCost : minimumCost > customerPricing.Minimum ? customerPricing.Minimum : minimumCost;

                // Log
                Log.Info(string.Format("TalkNowApi. CustomerId: {0} Limit amount: {1} Customer prepayment amount: {2}", customer.Id, limitAmount, customer.PrePaymentAmount));

                if (model.IsTalkNow) // If talk now
                {
                    // Check call in progress
                    var callInProgress = Services.Call.GetCallInProgressByCallerId(model.CustomerId);

                    if (callInProgress == null)
                    {
                        // If payment menthod is prepayment => Compare customer amount prepayment with customerPricing.Minimum
                        // If payment menthod is credit card => If charge success
                        switch (customer.PaymentMethod)
                        {
                            case PaymentMethod.CreditCard:
                                var result = Services.Payment.Authorization(CurrentUser.Id.ToString(), limitAmount);
                                if (!result.Success)
                                {
                                    return Json(new { Success = false, Error = CallMessage.BalanceIsExpire });
                                }
                                else
                                {
                                    Services.Payment.Void(result.Transaction.Id);
                                }
                                break;

                            default:
                                if (customer.PrePaymentAmount <= limitAmount)
                                {
                                    return Json(new { Success = false, Error = CallMessage.BalanceIsExpire });
                                }
                                break;
                        }

                        // If customer prepayment amount <= minimum cost => Notify for customer
                        if (customer.PrePaymentAmount <= minimumCost && PaymentMethod.PrePayment.Equals(customer.PaymentMethod))
                        {
                            CallHelper.NotifyBalanceCloseToExpiring(customer.UserName);
                        }

                        // Get specialization
                        SpecializationDto specialization = new SpecializationDto();

                        if (specialist.Profile.Specializations != null
                            && specialist.Profile.Specializations.Count > 0)
                        {
                            specialization = new SpecializationDto()
                            {
                                Id = specialist.Profile.Specializations[0].Id
                            };
                        }

                        // Save to database;
                        booking = Services.Booking.Create(new BookingDto
                        {
                            Customer = customer,
                            Specialist = specialist,
                            Enquiry = model.Enquiry,
                            CostPerMinute = customerPricing.TalkNow,
                            RatePerMinute = specialist.Profile.Specializations.FirstOrDefault().TalkNowRate,
                            SpecialistMinCharge = specialist.Profile.Specializations.FirstOrDefault().MinimumCharge,
                            CustomerMinCharge = customerPricing.Minimum,
                            CreatedDate = DateTime.UtcNow,
                            ModifiedDate = DateTime.UtcNow,
                            StartTime = DateTime.UtcNow,
                            EndTime = DateTime.UtcNow,
                            Status = BookingStatus.InProgress,
                            Type = BookingType.TalkNow,
                            Specialization = specialization,
                            IsApplyNoMinimumCharge = specialist.Profile.Specializations.FirstOrDefault().IsApplyNoMinimumCharge
                        });

                        // Generate twiml url
                        twiMLUrl = CallHelper.GenerateTwimlUrl(new CallContextModel
                        {
                            BookingId = booking.Id,
                            CallerId = booking.Customer.Id,
                            ReceiverId = booking.Specialist.Id,
                            IsCustomer = true,
                            NatureOfEnquiry = booking.Enquiry
                        });

                        // Set status for make call
                        status = true;
                    }
                    else // Have call inprogress
                    {
                        return Json(new { Success = false, Error = CallMessage.CallInProgress });
                    }
                }
                else // Make call from booking confirm
                {
                    // Get booking
                    booking = Services.Booking.GetById(model.BookingId);

                    // If payment menthod is prepayment => Compare customer amount prepayment with customerPricing.Minimum
                    // If payment menthod is credit card => If charge success
                    switch (customer.PaymentMethod)
                    {
                        case PaymentMethod.CreditCard:
                            var result = Services.Payment.Authorization(CurrentUser.Id.ToString(), limitAmount);
                            if (!result.Success)
                            {
                                // Show popup notify for specialist
                                CallHelper.ShowPopupNotifyInConference(booking.Specialist,
                                    ConferencePopupConst.CallFailsTitle, ConferencePopupConst.PrepaidBalanceForConsultant);

                                // Show popup notify for customer
                                CallHelper.ShowPopupNotifyInConference(booking.Customer,
                                    ConferencePopupConst.CallFailsTitle,
                                    string.Format(ConferencePopupConst.PrepaidBalanceForCustomer, booking.ReferenceNo));

                                // Return message error
                                return Json(new { Success = false });
                            }
                            else
                            {
                                Services.Payment.Void(result.Transaction.Id);
                            }
                            break;

                        default:
                            if (customer.PrePaymentAmount <= limitAmount)
                            {
                                // Show popup notify for specialist
                                CallHelper.ShowPopupNotifyInConference(booking.Specialist,
                                    ConferencePopupConst.CallFailsTitle, ConferencePopupConst.PrepaidBalanceForConsultant);

                                // Show popup notify for customer
                                CallHelper.ShowPopupNotifyInConference(booking.Customer,
                                    ConferencePopupConst.CallFailsTitle,
                                    string.Format(ConferencePopupConst.PrepaidBalanceForCustomer, booking.ReferenceNo));

                                // Return message error
                                return Json(new { Success = false });
                            }
                            break;
                    }

                    // If customer prepayment amount <= minimum cost => Notify for customer
                    if (booking.Customer.PrePaymentAmount <= minimumCost && PaymentMethod.PrePayment.Equals(booking.Customer.PaymentMethod))
                    {
                        CallHelper.NotifyBalanceCloseToExpiring(booking.Customer.UserName);
                    }

                    // Check call in progress
                    var callInProgress = Services.Call.GetCallInProgressByCallerId(model.SpecialistId);

                    if (callInProgress == null)
                    {
                        // Check make call fails to customer
                        if (booking.CallFails <= 3)
                        {
                            // Generate twiml url
                            twiMLUrl = CallHelper.GenerateTwimlUrl(new CallContextModel
                            {
                                BookingId = model.BookingId,
                                CallerId = model.SpecialistId,
                                ReceiverId = model.CustomerId,
                                IsCustomer = false,
                                NatureOfEnquiry = model.Enquiry
                            });

                            // Set status for make call
                            status = true;
                        }
                        else
                        {
                            // Show popup notify for specialist
                            CallHelper.ShowPopupNotifyInConference(booking.Specialist, ConferencePopupConst.CallFailsTitle,
                                string.Format(ConferencePopupConst.CallFailsContent,
                                booking.CallFails));

                            // Add to booking event
                            Services.Booking.CreateBookingEvent(new BookingEventDto
                            {
                                Booking = booking,
                                SourceUser = booking.Specialist,
                                TargetUser = booking.Customer,
                                ShortDescription = AlertShortDescription.FailedAttemptsCancellation,
                                Description = AlertDescription.FailedAttemptsCancellation,
                                CreatedDate = DateTime.UtcNow,
                                ModifiedDate = DateTime.UtcNow,
                                IsRead = false,
                                EmailAlertSubject = EmailAlertSubject.FailedAttemptsCancellation,
                                EmailAlertDetail = EmailAlertDetail.FailedAttemptsCancellation,
                                SMSAlertDetail = SMSAlertDetail.FailedAttemptsCancellation
                            });

                            // Return message error
                            return Json(new { Success = false });
                        }
                    }
                    else // Call in progress
                    {
                        return Json(new { Success = false, Error = CallMessage.CallInProgress });
                    }
                }

                if (status == true)
                {
                    // Make a call
                    var call = Services.Call.MakeCallForConsultantion(booking, twiMLUrl, model.IsTalkNow);
                    if (call.RestException == null)
                    {
                        return Json(new { Success = "True" });
                    }

                    // Log
                    Log.Error("TalkNowApi. Make call for consultation. Error: " + call.RestException.Message);

                    return Json(new { Success = "False", Error = CallMessage.SystemError });
                }

                return Json(new { Success = "False", Error = CallMessage.SystemError });
            }
            catch (Exception e)
            {
                // Log
                Log.Error("TalkNowAPI. Error", e);

                return Json(new { Success = "False", Error = CallMessage.SystemError });
            }
        }
        /// <summary>
        /// Send transcription request
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="userName"></param>
        /// <param name="email"></param>
        /// <param name="recordUrl"></param>
        /// <param name="recordDuration"></param>
        /// <param name="booking"></param>
        /// <returns> 0: Balance is not enough for transcript </returns>
        /// <returns> 1: Transcript is unsuccess </returns>
        /// <returns> 2: Transcript is success </returns>
        private int SendTranscriptionRequest(string userId, string userName,
                                                string email, string recordUrl,
                                                int recordDuration, BookingDto booking)
        {
            int result = 1;

            // Generate call back url for transcript
            string callBackUrlForTranscript = string.Format("{0}://{1}{2}?username={3}&email={4}", Request.Url.Scheme,
                                                Request.Url.Authority, Url.Action("TranscriptionResult", "Transcription"),
                                                userName, email);

            decimal ratePerMinitue = Services.SystemConfig.GetRatePerMinutetForTranscription();
            decimal amount = Utilities.RoundMoney(Utilities.RoundMinute(recordDuration) * ratePerMinitue);
            var paymentResult = Services.Payment.Authorization(userId, amount);

            if (paymentResult.Success)
            {
                try
                {
                    // Transcript
                    Services.Transcription.TranscriptionRequest(recordUrl, TelAPI.TranscriptionType.Auto, callBackUrlForTranscript);

                    // Settle transaction
                    Services.Payment.Settlement(paymentResult.Transaction.Id);

                    // Create invoice and send invoice email
                    Services.Invoices.CreateTranscriptionInvoice(amount, recordDuration,
                                                                    ratePerMinitue, booking,
                                                                    Services.Users.GetByUserName(userName), null);

                    result = 2;
                }
                catch (Exception e)
                {
                    Log.Error("ConferenceController_SendTranscriptionRequest. Error: ", e);
                    result = 1;
                }
            }

            return result;
        }
示例#11
0
        // ============================ INTERACTING WITH TWILIO ============================
        /// <summary>
        /// Make call for consultantion
        /// </summary>
        /// <param name="booking"></param>
        /// <param name="twiMLUrl"></param>
        /// <param name="isTalkNow"></param>
        /// <returns></returns>
        public Call MakeCallForConsultantion(BookingDto booking, string twiMLUrl, bool isTalkNow)
        {
            try
            {
                string fullPhoneNo = booking.Specialist.MobileCountryCode + booking.Specialist.MobilePhone;

                if (!isTalkNow) // If call from confirm booking
                {
                    fullPhoneNo = booking.Customer.MobileCountryCode + booking.Customer.MobilePhone;
                }

                var call = Dial(twiMLUrl, fullPhoneNo);

                // Update into database
                // Default make call for talk now
                var callDto = new CallDto
                {
                    ReceiverSid = call.Sid,
                    Booking = booking,
                    ReceiverStatus = call.Status,
                    Caller = booking.Customer,
                    Receiver = booking.Specialist,
                    StartTime = DateTime.UtcNow,
                    EndTime = DateTime.UtcNow,
                    CreatedDate = DateTime.UtcNow,
                    ModifiedDate = DateTime.UtcNow
                };

                // If make call for booking
                if (!isTalkNow)
                {
                    callDto.Caller = booking.Specialist;
                    callDto.Receiver = booking.Customer;
                }

                // Insert to database
                Create(callDto);

                return call;
            }
            catch (Exception e)
            {
                // Log
                Log.Error("CallService_MakeCallForTalkNow_Error making call",
                   e);

                throw new Exception("Error making call. Error: " + e.Message);
            }
        }
示例#12
0
 // -------------------- .CREATE -------------------- //
 // -------------------- UPDATE -------------------- //
 /// <summary>
 /// Update booking
 /// </summary>
 /// <param name="booking"></param>
 public void Update(BookingDto booking)
 {
     Repository.Update<Booking>(booking.ExposedAs<Booking>(Repository));
     UnitOfWork.Save();
 }
示例#13
0
        // -------------------- .GET -------------------- //
        // -------------------- CREATE -------------------- //
        /// <summary>
        /// Create a booking
        /// </summary>
        /// <param name="booking"></param>
        /// <returns></returns>
        public BookingDto Create(BookingDto booking)
        {
            // IRepository repository = Repository;
            var book = booking.ExposedAs<Booking>(Repository);
            book.ReferenceNo = GetBookingReferenceNo();
            // Convert date time to UTC
            book.CreatedDate = DateTime.UtcNow;
            book.ModifiedDate = DateTime.UtcNow;

            Repository.Insert<Booking>(book);
            UnitOfWork.Save();

            booking = book.ExposedAs<BookingDto>();

            // Add to booking event for consultant
            if (booking.Type != BookingType.TalkNow)
            {
                var bookingEventDto = new BookingEventDto
                {
                    Booking = booking,
                    SourceUser = booking.Customer,
                    TargetUser = booking.Specialist,
                    ShortDescription = AlertShortDescription.BookingRequestMade,
                    Description = AlertDescription.BookingRequestMade,
                    CreatedDate = DateTime.UtcNow,
                    ModifiedDate = DateTime.UtcNow,
                    IsRead = false,
                    EmailAlertSubject = EmailAlertSubject.BookingRequestMade,
                    EmailAlertDetail = EmailAlertDetail.BookingRequestMade,
                    SMSAlertDetail = SMSAlertDetail.BookingRequestMade
                };

                CreateBookingEvent(bookingEventDto);
            }

            return booking;
        }
 public SpecialistProfileViewModel()
 {
     Booking = new BookingDto();
 }
示例#15
0
        /// <summary>
        /// Update value for booking when customer click Cancel defer
        /// </summary>
        /// <param name="booking"></param>
        /// <param name="services"></param>
        /// <returns></returns>
        public static bool UpdateCancelBookingForDefer(BookingDto booking, IServices services)
        {
            bool isSuccess = false;
            if (booking != null)
            {
                // Update booking info
                booking.Status = BookingStatus.Cancel;
                booking.StartTime = null;
                booking.EndTime = null;

                //booking.Type = BookingType.BookTime;

                // Update booking to databse
                try
                {
                    services.Booking.Update(booking);
                    isSuccess = true;

                    // Reload alert and booking list
                    NotifyHelper.ReloadAlert(booking.Specialist.UserName);
                    NotifyHelper.ReloadAlert(booking.Customer.UserName);
                }
                catch (Exception e)
                {
                    // Log
                    Log.Error("Talk now defer error", e);
                }
            }
            return isSuccess;
        }
        public ActionResult TalkNowRequest(Guid specialistId, string enquiry)
        {
            try
            {
                if (specialistId != null)
                {
                    // Get Customer and Specialist
                    var customer = Services.Users.GetByUserName(CurrentUser.UserName);

                    // Check call in progress
                    var call = Services.Call.GetCallInProgressByCallerId(customer.Id);

                    if (call == null)
                    {
                        var specialist = Services.Users.GetUserById(specialistId);
                        var customerPricing = Services.Booking.GetCustomerPricing(specialist.Profile.Specializations.FirstOrDefault().Id);

                        var minimumBookingTime = (int)Services.SystemConfig.GetValueByKey(ParamatricBusinessRules.MINIMUM_BOOKING.ToString());
                        var minimumCost = minimumBookingTime * customerPricing.TalkNow;

                        var limitAmount = customerPricing.IsApplyNoMinimumCharge ?
                                 minimumCost : minimumCost > customerPricing.Minimum ? customerPricing.Minimum : minimumCost;

                        // Log
                        Log.Info(string.Format("TalkNowRequest. UserId:: {0} Limit amount: {1} Customer prepayment amount: {2}", customer.Id, limitAmount, customer.PrePaymentAmount));

                        // If payment menthod is prepayment => Compare customer amount prepayment with customerPricing.Minimum
                        // If payment menthod is credit card => If charge success
                        switch (customer.PaymentMethod)
                        {
                            case PaymentMethod.CreditCard:
                                var result = Services.Payment.Authorization(CurrentUser.Id.ToString(), limitAmount);
                                if (!result.Success)
                                {
                                    return Json(new { Status = false, Message = "PrepaymentExpires" }, JsonRequestBehavior.AllowGet);
                                }
                                else
                                {
                                    Services.Payment.Void(result.Transaction.Id);
                                }
                                break;

                            default:
                                if (customer.PrePaymentAmount <= limitAmount)
                                {
                                    return Json(new { Status = false, Message = "PrepaymentExpires" }, JsonRequestBehavior.AllowGet);
                                }
                                break;
                        }

                        // If customer prepayment amount <= minimum cost => Notify for customer
                        if (customer.PrePaymentAmount <= minimumCost
                            && PaymentMethod.PrePayment.Equals(customer.PaymentMethod))
                        {
                            CallHelper.NotifyBalanceCloseToExpiring(customer.UserName);
                        }

                        // Save to database
                        var bookingContext = new BookingDto
                        {
                            Customer = customer,
                            Specialist = specialist,
                            Enquiry = enquiry,
                            CustomerMinCharge = customerPricing.Minimum,
                            SpecialistMinCharge = specialist.Profile.Specializations.FirstOrDefault().MinimumCharge,
                            CostPerMinute = customerPricing.TalkNow,
                            RatePerMinute = specialist.Profile.Specializations.FirstOrDefault().TalkNowRate,
                            Type = BookingType.TalkNow,
                            CreatedDate = DateTime.UtcNow,
                            ModifiedDate = DateTime.UtcNow,
                            StartTime = DateTime.UtcNow,
                            EndTime = DateTime.UtcNow,
                            Specialization = specialist.Profile.Specializations.FirstOrDefault(),
                            IsApplyNoMinimumCharge = specialist.Profile.Specializations.FirstOrDefault().IsApplyNoMinimumCharge
                        };

                        var booking = Services.Booking.Create(bookingContext);

                        return Json(new { Status = true, BookId = booking.Id }, JsonRequestBehavior.AllowGet);
                    }
                    else
                    {
                        // Return error: Have call in progress
                        return Json(new { Status = false, Message = "CallInProgress" }, JsonRequestBehavior.AllowGet);
                    }
                }
                else
                {
                    return Json(new { Status = false }, JsonRequestBehavior.AllowGet);
                }
            }
            catch (Exception e)
            {
                // Log
                Log.ErrorFormat("Talk now request. Error", e);

                return Json(new { Status = false }, JsonRequestBehavior.AllowGet);
            }
        }
示例#17
0
        /// <summary>
        /// Update value for booking when customer click confirm defer
        /// </summary>
        /// <param name="booking"></param>
        /// <param name="isDefer"></param>
        /// <param name="services"></param>
        /// <returns></returns>
        public static bool UpdateConfirmBookingForDefer(BookingDto booking, bool isDefer, IServices services)
        {
            try
            {
                if (booking != null)
                {
                    // Update booking info
                    if (isDefer)
                    {
                        booking.Status = BookingStatus.Confirmed;
                        booking.Type = BookingType.TalkNow;
                    }
                    else // Reschedule
                    {
                        booking.Status = BookingStatus.Requested;
                        booking.Type = BookingType.StandardHour;
                        // Ticket: 257777
                        booking.CostPerMinute = services.Booking.GetCustomerPrice(
                            booking.Specialist.Profile.Specializations.First().Id,
                            BookingType.StandardHour);
                    }

                    // Start time = Start time when book add defer/reschedule minute
                    // End time = End time when book add defer/reschedule minute
                    //booking.StartTime = booking.StartTime.Value.AddMinutes((double)booking.Deferral);
                    //booking.EndTime = booking.EndTime.Value.AddMinutes((double)booking.Deferral);

                    // Update booking to databse
                    services.Booking.Update(booking);

                    // Reload alert and booking list
                    NotifyHelper.ReloadAlert(booking.Specialist.UserName);
                    NotifyHelper.ReloadAlert(booking.Customer.UserName);

                    return true;
                }
            }
            catch (Exception e)
            {
                Log.Error("Talk now defer error", e);
            }

            return false;
        }
        public ActionResult PastBookingOLD(Guid bookingId)
        {
            try
            {
                ViewBag.IsSpecialist = false;
                List<InvoiceDto> invoices = Services.Invoices.GetInvoiceByBookingId(bookingId);
                InvoiceDto invoice = new InvoiceDto();
                BookingDto booking = new BookingDto();

                if (invoices == null || !invoices.Any())
                {
                    booking = Services.Booking.GetById(bookingId);
                }
                else
                {
                    booking = invoices.First(i => i.Booking.Id == bookingId).Booking;
                    invoice = invoices.First(i => i.User.Id == booking.Customer.Id && i.Type == InvoiceType.Consultation);
                }

                ViewBag.IsSpecialist = IsSpecialist();

                PopupPastBookingViewModel popupPastBooking = new PopupPastBookingViewModel();
                //TRI:TODO
                popupPastBooking.PopupBooking = BookingHelper.LoadBookingByBookingId(booking, ViewBag.IsSpecialist);
                popupPastBooking.IsFavourite = Services.Users.IsFavourite(popupPastBooking.PopupBooking.SpecialistId, CurrentUser.Id);
                popupPastBooking.PopupBooking.RatingRatio = (int)Math.Round(Services.Booking.GetRatingByBooking(booking.Id), 0, MidpointRounding.AwayFromZero);
                var specialist = booking.Specialist;

                popupPastBooking.SpecialistStatus = specialist.CurrentAvailabilityStatus;
                //check specilist is calling with customer to change curremt status to "not avaiable"
                if (!AvailabilityStatus.NotAvailable.Equals(popupPastBooking.SpecialistStatus)
                    && Services.Call.CheckCallInProgressBySpecialistId(specialist.Id))
                {
                    popupPastBooking.SpecialistStatus = AvailabilityStatus.NotAvailable;
                }

                popupPastBooking.Invoice = new InvoiceDto { Amount = 0 };
                if (invoice != null)
                {
                    popupPastBooking.Invoice = invoice;

                    if (!ConsultationType.MinimumCharge.Equals(invoice.ConsultationType))
                    {
                        popupPastBooking.ConsultationFee = invoice.Duration * booking.RatePerMinute;
                        popupPastBooking.ApplicableCost = invoice.Amount;
                    }
                    else
                    {
                        popupPastBooking.ApplicableCost = invoice.DeclineBookingRate;
                        var specialistInvoice = Services.Invoices.GetByBookingIdAndUserId(booking.Id, booking.Specialist.Id);
                        popupPastBooking.ConsultationFee = specialistInvoice.DeclineBookingRate;
                    }
                }

                var callLog = Services.Call.GetByBookingId(bookingId);

                if (callLog != null)
                {
                    var twilioServer = System.Configuration.ConfigurationManager.AppSettings["Twilio_ApiServer"];

                    // Check record url
                    var recordUrl = callLog.RecordUrl.Contains(twilioServer)
                        ? Utilities.ConvertLinkRecord(callLog.RecordSid)
                        : S3ReaderHelper.CombineS3Root(callLog.RecordUrl);

                    popupPastBooking.CallId = callLog.Id;
                    popupPastBooking.CallStartTime = TeleConsult.Web.Code.Helpers.DateTimeHelper.ConvertToCurrentTimeZone(callLog.StartTime.GetValueOrDefault(DateTime.UtcNow));
                    popupPastBooking.CallEndTime = TeleConsult.Web.Code.Helpers.DateTimeHelper.ConvertToCurrentTimeZone(callLog.EndTime.GetValueOrDefault(DateTime.UtcNow));
                    popupPastBooking.DurationMinute = callLog.Duration;
                    if (!string.IsNullOrWhiteSpace(callLog.RecordSid))
                    {
                        string urlTwilio = string.Format(Settings.UrlCallRecord, Settings.Twilio.Key);
                        popupPastBooking.RecordUrl = string.Format("{0}{1}", urlTwilio, callLog.RecordUrl);
                    }
                    popupPastBooking.IsFeedback = Services.Call.CheckExistFeedbackAndRatingByCallId(callLog.Id);
                    popupPastBooking.RecordUrl = recordUrl;
                }
                return PartialView("BookingPopUpTemplate/_PastBooking", popupPastBooking);
            }
            catch (Exception e)
            {
                Log.Error("Past booking", e);
                throw;
            }
        }