public bool Insert(Appointment appointment, ref string message)
 {
     try
     {
         if (!ValidateAppointment(appointment, false, ref message)) return false;
         DataRepository.AppointmentProvider.Insert(appointment);
         GlobalUtilities.WriteLog(BuildApptHistory(appointment), null, appointment.UpdateUser, DataRepository.Provider.ExecuteDataSet);
         SendEmail(appointment, false);
         return true;
     }
     catch (Exception ex)
     {
         LoggerController.WriteLog(System.Runtime.InteropServices.Marshal.GetExceptionCode(), ex, Network.GetIpClient());
     }
     return false;
 }
        /// <summary>
        /// Gui email cho doctor sau khi insert/update
        /// </summary>
        /// <param name="appointment"></param>
        /// <param name="isUpdate"></param>
        /// <returns></returns>
        private bool SendEmail(Appointment appointment, bool isUpdate)
        {
            try
            {
                var objPatient = DataRepository.VcsPatientProvider.GetByPatientCode(appointment.PatientCode)[0];

                DataRepository.AppointmentProvider.DeepLoad(appointment);
                string strSubject = String.Format("{3} Appointment: {0}{1}{2}", appointment.ServicesIdSource.Title,
                                                  objPatient.FirstName, objPatient.LastName, isUpdate ? "Change" : "New");
                string strBody = isUpdate ? "You have a new change for appointment" : "You have a new appointment";
                string strSummary = string.Empty;
                string strDescription = string.Empty;
                string strLocation = appointment.RoomId == null ? " - " :
                    String.Format("Room {0}", appointment.RoomIdSource.Title);
                string strAlarmSummary = String.Format("{0} minutes left for appointment with {1} {2}",
                    ServiceFacade.SettingsHelper.TimeLeftRemindAppointment
                    , objPatient.FirstName, objPatient.LastName);
                var objMail = new MailAppointment(strSubject, strBody, strSummary, strDescription, strLocation, strAlarmSummary,
                    Convert.ToDateTime(appointment.StartTime), Convert.ToDateTime(appointment.EndTime));
                objMail.AddMailAddress(appointment.UsernameSource.Email, appointment.UsernameSource.DisplayName);
                objMail.SendMail();

                return true;
            }
            catch (Exception ex)
            {
                LoggerController.WriteLog(System.Runtime.InteropServices.Marshal.GetExceptionCode(), ex, Network.GetIpClient());
            }
            return false;
        }
        public bool Update(ref Appointment appointment, ref string message)
        {
            try
            {
                // Goi ham kiem tra appointment
                if (!ValidateAppointment(appointment, true, ref message)) return false;

                // Get old roster by id
                var oldAppt = DataRepository.AppointmentProvider.GetById(appointment.Id);

                // Validate if roster's not existed
                // return message, nothing more
                if (oldAppt == null || oldAppt.IsDisabled)
                {
                    message = "There is no appointment to update.";
                    return false;
                }

                SingletonLogger.Instance.Debug(String.Format("{0}-------{1}-------IP: {2}", "Update Appointment",
                                                             JsonConvert.SerializeObject(new
                                                                 {
                                                                     appointment.Username,
                                                                     appointment.ServicesId,
                                                                     appointment.StatusId,
                                                                     appointment.EndTime,
                                                                     appointment.StartTime,
                                                                     appointment.RosterId,
                                                                     appointment.PatientCode,
                                                                     appointment.UpdateUser,
                                                                     appointment.CreateUser
                                                                 }), Network.GetIpClient()));

                var comparedAppt = oldAppt.Copy();

                // Gan gia tri moi
                // Ghi log moi khi thay doi gia tri
                oldAppt.PatientCode = appointment.PatientCode;
                oldAppt.Username = appointment.Username;
                oldAppt.RoomId = appointment.RoomId;
                oldAppt.StatusId = appointment.StatusId;
                oldAppt.StartTime = appointment.StartTime;
                oldAppt.EndTime = appointment.EndTime;
                oldAppt.Note = appointment.Note;

                GlobalUtilities.WriteLog(BuildApptHistory(comparedAppt), BuildApptHistory(oldAppt),
                                         appointment.UpdateUser, DataRepository.Provider.ExecuteDataSet);

                comparedAppt.PatientCode = appointment.PatientCode;
                comparedAppt.Username = appointment.Username;
                comparedAppt.Note = appointment.Note;
                comparedAppt.RoomId = appointment.RoomId;
                comparedAppt.StatusId = appointment.StatusId;
                comparedAppt.StartTime = appointment.StartTime;
                comparedAppt.EndTime = appointment.EndTime;

                oldAppt.RosterId = appointment.RosterId;
                oldAppt.ServicesId = appointment.ServicesId;
                oldAppt.UpdateUser = appointment.UpdateUser;

                DataRepository.AppointmentProvider.Update(oldAppt);

                // Gan lai doi tuong appointment
                appointment = oldAppt;
                SendEmail(appointment, true);
                return true;
            }
            catch (Exception ex)
            {
                LoggerController.WriteLog(System.Runtime.InteropServices.Marshal.GetExceptionCode(), ex, Network.GetIpClient());
            }
            return false;
        }
        /// <summary>
        /// Kiem tra appointment
        /// </summary>
        /// <param name="oldAppt"></param>
        /// <param name="isUpdate"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private bool ValidateAppointment(Appointment oldAppt, bool isUpdate, ref string message)
        {
            try
            {
                #region Validate exsited
                // Kiem tra status co ton tai khong
                var objStatus = DataRepository.StatusProvider.GetById(oldAppt.StatusId);
                if (objStatus == null)
                {
                    message = "Status is not exist.";
                    return false;
                }

                // Kiem tra doctor co ton tai khong
                var objUser = DataRepository.UsersProvider.GetByUsername(oldAppt.Username);
                if (objUser == null || objUser.IsDisabled)
                {
                    message = "Doctor is not exist.";
                    return false;
                }

                // Kiem tra patient co ton tai khong
                var objPatients = DataRepository.VcsPatientProvider.GetByPatientCode(oldAppt.PatientCode);
                if (objPatients == null || !objPatients.Any())
                {
                    message = "Patient is not exist.";
                    return false;
                }
                var objPatient = objPatients[0];

                // Kiem tra room co ton tai khong
                Room objRoom = null;
                oldAppt.RoomId = oldAppt.RoomId != CommonBO.NonValue ? oldAppt.RoomId : null;
                if (oldAppt.RoomId != null)
                {
                    objRoom = DataRepository.RoomProvider.GetById(Convert.ToInt32(oldAppt.RoomId));
                    if (objRoom == null || objRoom.IsDisabled)
                    {
                        message = "Room is not exist.";
                        return false;
                    }

                    // Cho nay can kiem tra phong co dang su dung ko
                    // Hien tai thi chua
                }
                #endregion

                #region Validate data
                // Kiem tra ngay bat dau, ngay ket thuc
                if (oldAppt.StartTime >= oldAppt.EndTime)
                {
                    message = "End time must be greater than start time.";
                    return false;
                }

                // Kiểm tra xem appt có được tạo vào thời điểm đã qua không
                // Riêng trường hợp update thì cho phép update trong ngày
                var dtNow = DateTime.Now;
                dtNow = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day);
                if ((DateTime.Now >= oldAppt.StartTime && !isUpdate)
                    || (dtNow > oldAppt.EndTime && isUpdate))
                {
                    message = "You can not change appointment to passed time.";
                    return false;
                }

                // Validate note's max length
                if (oldAppt.Note.Length > 500)
                {
                    message = String.Format(BoFactory.MessageConfigBO.GetMessage(MessageCode.StringCode.OverMaxLength), "Note", 500);
                    return false;
                }
                #endregion

                #region Kiem tra xem doctor duoc tao appointment co dang ky Roster hay khong
                int count;
                // Get roster list
                var lstRoster =
                    DataRepository.RosterProvider.GetPaged(
                        String.Format("Username = '******' AND StartTime <= '{1}' AND EndTime >= '{2}' AND IsDisabled = 'False'",
                                      oldAppt.Username, String.Format("{0:yyyy-MM-dd HH:mm:ss}", oldAppt.StartTime),
                                      String.Format("{0:yyyy-MM-dd HH:mm:ss}", oldAppt.EndTime)), string.Empty, 0,
                        ServiceFacade.SettingsHelper.GetPagedLength, out count);

                // If there is no roster, return error
                if (!lstRoster.Any())
                {
                    message = String.Format("Cannot create appointment because {0} has no roster from {1} to {2}."
                        , objUser.DisplayName, String.Format("{0:yyyy-MM-dd HH:mm}", oldAppt.StartTime)
                        , String.Format("{0:yyyy-MM-dd HH:mm}", oldAppt.EndTime));
                    return false;
                }

                // If there has some rosters but not is booked, return error
                DataRepository.RosterProvider.DeepLoad(lstRoster);
                //var lstRosterType = lstRoster.Select(x => x.RosterTypeIdSource.IsBooked);
                //if (!lstRosterType.Any())
                //{
                //    message = String.Format("Cannot create appointment because roster {0} is not booked roster."
                //        , lstRoster[0].RosterTypeIdSource.Title);
                //    return false;
                //}
                #endregion

                #region Check Conflict
                // Neu cac trang thai khong phai la cancel, done, block [may cai nay co the thay doi] thi kiem tra conflict
                if (oldAppt.StatusId != ApptStatus.Cancelled && oldAppt.StatusId != ApptStatus.Completed)
                {
                    // Check conflict Patient
                    if (!CheckConflict("PatientCode", oldAppt.PatientCode, string.Empty,
                        String.Format("{0} {1}", objPatient.FirstName, objPatient.LastName), Convert.ToDateTime(oldAppt.StartTime)
                            , Convert.ToDateTime(oldAppt.EndTime), oldAppt.Id, ref message))
                    {
                        message = String.Format("Cannot create appointment because {0} has another appointment from {1} to {2}."
                            , objPatient.FirstName + " " + objPatient.LastName
                            , String.Format("{0:yyyy-MM-dd HH:mm}", oldAppt.StartTime)
                            , String.Format("{0:yyyy-MM-dd HH:mm}", oldAppt.EndTime));
                        return false;
                    }

                    if (!CheckConflict("Username", objUser.Username, string.Empty, objUser.DisplayName
                        , Convert.ToDateTime(oldAppt.StartTime), Convert.ToDateTime(oldAppt.EndTime), oldAppt.Id, ref message))
                    {
                        return false;
                    }

                    // Check conflict Room
                    if (oldAppt.RoomId != null && oldAppt.RoomId != CommonBO.NonValue && objRoom != null)
                    {
                        if (!CheckConflict("RoomId", oldAppt.RoomId.ToString(), "Room"
                            , objRoom.Title, Convert.ToDateTime(oldAppt.StartTime), Convert.ToDateTime(oldAppt.EndTime), oldAppt.Id, ref message))
                        {
                            return false;
                        }
                    }
                }
                #endregion

                // Tao Id moi bang cach truyen Id cu vao
                // Neu la update thi khong can RosterId moi
                oldAppt.Id = isUpdate ? oldAppt.Id : BoFactory.IdBO.AppointmentId(oldAppt.Id);
                oldAppt.ServicesId = objUser.ServicesId;
                oldAppt.RosterId = lstRoster[0].Id;

                return true;
            }
            catch (Exception ex)
            {
                LoggerController.WriteLog(System.Runtime.InteropServices.Marshal.GetExceptionCode(), ex, Network.GetIpClient());
            }
            return false;
        }
        public void InsertHistory(Appointment appointment, string username, string fromStatus, string toStatus)
        {
            try
            {
                var patient = DataRepository.PatientProvider.GetByPatientCode(appointment.PatientCode);

                var history = new AppointmentHistory
                    {
                        Guid = Guid.NewGuid(),
                        AppointmentId = appointment.Id,
                        Note = String.Format("User {0} change appointment {1} from status {2} to {3}, patient {4}, user {5}"
                        , username, appointment.Id, fromStatus, toStatus, patient.LastName, appointment.Username),
                        CreateUser = username,
                        CreateDate = DateTime.Now
                    };
                DataRepository.AppointmentHistoryProvider.Insert(history);
            }
            catch (Exception ex)
            {
                LoggerController.WriteLog(System.Runtime.InteropServices.Marshal.GetExceptionCode(), ex, Network.GetIpClient());
            }
        }
        public object BuildApptHistory(Appointment appt)
        {
            try
            {
                //var patient = DataRepository.VcsPatientProvider.GetByPatientCode(appt.PatientCode);
                var room = DataRepository.RoomProvider.GetById(Convert.ToInt32(appt.RoomId));
                var service = DataRepository.ServicesProvider.GetById(Convert.ToInt32(appt.ServicesId));

                if (service != null)
                    return new AppointmentLog
                    {
                        Id = appt.Id,
                        PatientCode = appt.PatientCode,
                        Username = appt.Username,
                        Room = room == null ? string.Empty : room.Title,
                        Service = service.Title,
                        Status = appt.StatusId,
                        StartTime = Convert.ToDateTime(appt.StartTime),
                        EndTime = Convert.ToDateTime(appt.EndTime),
                        Note = appt.Note,
                    };
            }
            catch (Exception ex)
            {
                LoggerController.WriteLog(System.Runtime.InteropServices.Marshal.GetExceptionCode(), ex, Network.GetIpClient());
            }
            return null;
        }