private static string GetAppointmentClass(Appointment a)
        {
            var classes = new List<string>();
            if (a.Status == (int)TypeAppointmentStatus.NotAccomplished)
                classes.Add("not-accomplished");

            switch ((TypeAppointmentStatus)a.Status)
            {
                case TypeAppointmentStatus.Accomplished:
                    classes.Add("accomplished");
                    break;
                case TypeAppointmentStatus.NotAccomplished:
                    classes.Add("not-accomplished");
                    break;
                case TypeAppointmentStatus.Discarded:
                case TypeAppointmentStatus.Undefined:
                    break;
                default:
                    throw new Exception("Unsupported appointment status");
            }

            switch ((TypeAppointment)a.Type)
            {
                case TypeAppointment.GenericAppointment:
                    classes.Add("generic-appointment");
                    break;
                case TypeAppointment.MedicalAppointment:
                    classes.Add("medical-appointment");
                    break;
                default:
                    throw new Exception("Unsupported appointment type.");
            }

            return string.Join(" ", classes);
        }
        public static string GetAppointmentText(Appointment a)
        {
            string result = null;
            switch ((TypeAppointment)a.Type)
            {
                case TypeAppointment.GenericAppointment:
                    result = a.Description;
                    break;
                case TypeAppointment.MedicalAppointment:
                    result = a.Patient.Person.FullName;
                    break;
                default:
                    throw new Exception("Unsupported appointment type.");
            }
            if (string.IsNullOrEmpty(result))
                throw new Exception("The appointment text cannot be null. This will trigger a client-side exception");

            return result;
        }
        public ActionResult Edit(AppointmentViewModel formModel)
        {
            // Custom model validation.
            if (formModel.IsGenericAppointment)
            {
                // This is a generic appointment, so we must clear validation for patient.
                this.ModelState.ClearPropertyErrors(() => formModel.PatientId);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientCode);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientName);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientNameLookup);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientGender);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientFirstAppointment);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientEmail);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientDateOfBirth);
                this.ModelState.ClearPropertyErrors(() => formModel.HealthInsuranceId);
                this.ModelState.ClearPropertyErrors(() => formModel.HealthInsuranceName);
            }
            else if (formModel.PatientFirstAppointment)
            {
                // This is a medical appointment, so we must clear validation for generic appointment.
                this.ModelState.ClearPropertyErrors(() => formModel.Description);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientId);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientNameLookup);
            }
            else
            {
                // This is a medical appointment, so we must clear validation for generic appointment.
                this.ModelState.ClearPropertyErrors(() => formModel.Description);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientCode);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientName);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientGender);
                this.ModelState.ClearPropertyErrors(() => formModel.PatientDateOfBirth);

                if (formModel.PatientId != null)
                {
                    var patient = this.db.Patients.FirstOrDefault(p => p.Id == formModel.PatientId);

                    if (patient == null)
                    {
                        this.ModelState.AddModelError<AppointmentViewModel>(
                            model => model.PatientNameLookup,
                            "O paciente informado não foi encontrado no banco de dados");
                    }
                    else if (patient.Person.FullName != formModel.PatientNameLookup)
                    {
                        this.ModelState.AddModelError<AppointmentViewModel>(
                            model => model.PatientNameLookup,
                            "O paciente informado foi encontrado mas o nome não coincide");
                    }
                }
            }

            // Verify if appoitment hours are consistent
            {
                DoDateAndTimeValidation(formModel, this.GetPracticeLocalNow(), formModel.Id);
            }

            // Verify if we're creating an appointment for the future with a Status set
            if (!string.IsNullOrEmpty(formModel.Start))
            {
                if (formModel.LocalDateTime + DateTimeHelper.GetTimeSpan(formModel.Start) > this.GetPracticeLocalNow())
                    if (formModel.Status != (int)TypeAppointmentStatus.Undefined)
                        ModelState.AddModelError<AppointmentViewModel>(
                            model => model.Status,
                            "Não é permitido determinar o Status para consultas agendadas para o futuro");
            }

            // Verify if the patient code is valid
            if (formModel.PatientFirstAppointment && formModel.PatientCode != null)
            {
                var patientCodeAsInt = default(int);
                int.TryParse(formModel.PatientCode, out patientCodeAsInt);
                if (patientCodeAsInt != default(int) && this.db.Patients.Any(p => p.Code == patientCodeAsInt))
                    this.ModelState.AddModelError<AppointmentViewModel>(
                        model => model.PatientCode, "O código do paciente informado pertence a outro paciente");
            }

            // Saving data if model is valid.
            if (this.ModelState.IsValid)
            {
                // Creating the appointment.
                Appointment appointment = null;

                if (formModel.Id == null)
                {
                    appointment = new Appointment
                        {
                            PracticeId = this.DbUser.PracticeId,
                            CreatedOn = this.UtcNowGetter(),
                            DoctorId = formModel.DoctorId,
                            CreatedById = this.DbUser.Id,
                        };
                    this.db.Appointments.AddObject(appointment);
                }
                else
                {
                    var currentUserPracticeId = this.DbUser.PracticeId;

                    appointment = this.db.Appointments
                        .Where(a => a.Id == formModel.Id).FirstOrDefault(a => a.Doctor.Users.FirstOrDefault().PracticeId == currentUserPracticeId);

                    // If the appointment does not exist, or does not belongs to the current practice,
                    // it should go to a view indicating that.
                    if (appointment == null)
                        return View("NotFound", formModel);
                }

                var appointmentStart = ConvertToUtcDateTime(this.DbPractice,
                    formModel.LocalDateTime + DateTimeHelper.GetTimeSpan(formModel.Start));

                var appointmentEnd = ConvertToUtcDateTime(this.DbPractice,
                    formModel.LocalDateTime + DateTimeHelper.GetTimeSpan(formModel.End));

                if (appointment.Start != appointmentStart)
                    appointment.Notified = false;

                appointment.Start = appointmentStart;
                appointment.End = appointmentEnd;

                appointment.Status = (int)formModel.Status;

                // Setting the appointment type and associated properties.
                // - generic appointment: has description, date and time interval
                // - medical appointment: has patient, date and time interval
                if (formModel.IsGenericAppointment)
                {
                    appointment.Description = formModel.Description;
                    appointment.Type = (int)TypeAppointment.GenericAppointment;
                }
                else
                {
                    appointment.Type = (int)TypeAppointment.MedicalAppointment;
                    appointment.HealthInsuranceId = formModel.HealthInsuranceId;

                    if (formModel.PatientFirstAppointment)
                    {
                        appointment.Patient = new Patient
                            {
                                Person =
                                    new Person
                                        {
                                            FullName = formModel.PatientName,
                                            Gender = (short)formModel.PatientGender,
                                            DateOfBirth =
                                                ConvertToUtcDateTime(this.DbPractice, formModel.PatientDateOfBirth.Value),
                                            PhoneCell = formModel.PatientPhoneCell,
                                            PhoneLand = formModel.PatientPhoneLand,
                                            CreatedOn = this.GetUtcNow(),
                                            PracticeId = this.DbUser.PracticeId,
                                            Email = formModel.PatientEmail,
                                            EmailGravatarHash = GravatarHelper.GetGravatarHash(formModel.PatientEmail)
                                        },
                                Code = int.Parse(formModel.PatientCode),
                                LastUsedHealthInsuranceId = formModel.HealthInsuranceId,
                                Doctor = this.Doctor,
                                PracticeId = this.DbUser.PracticeId,
                            };
                    }
                    else
                    {
                        var patient = this.db.Patients.Single(p => p.Id == formModel.PatientId);
                        patient.LastUsedHealthInsuranceId = formModel.HealthInsuranceId;
                        appointment.PatientId = formModel.PatientId.Value;
                    }
                }

                // Returning a JSON result, indicating what has happened.
                try
                {
                    this.db.SaveChanges();
                    return this.Json((dynamic)new { status = "success" }, JsonRequestBehavior.AllowGet);
                }
                catch (Exception ex)
                {
                    return this.Json((dynamic)new
                    {
                        status = "error",
                        text = "Não foi possível salvar a consulta. Erro inexperado",
                        details = ex.Message
                    }, JsonRequestBehavior.AllowGet);
                }
            }

            this.ViewBag.IsEditingOrCreating = this.RouteData.Values["action"].ToString()
                .ToLowerInvariant() == "edit" ? 'E' : 'C';

            return this.View("Edit", formModel);
        }
        public void Delete_WhenTheresAnAppointment()
        {
            PatientsController controller;
            Patient patient;

            try
            {
                var docAndre = Firestarter.Create_CrmMg_Psiquiatria_DrHouse_Andre(this.db);
                var mr = new MockRepository(true);
                controller = mr.CreateController<PatientsController>();
                Firestarter.CreateFakePatients(docAndre, this.db, 1);

                // we now have 1 patient
                patient = this.db.Patients.FirstOrDefault();
                Assert.IsNotNull(patient);
                var referenceTime = DateTime.UtcNow;

                var appointment = new Appointment()
                {
                    Doctor = docAndre,
                    CreatedBy = docAndre.Users.First(),
                    CreatedOn = referenceTime,
                    PatientId = patient.Id,
                    Start = referenceTime,
                    End = referenceTime + TimeSpan.FromMinutes(30),
                    PracticeId = docAndre.PracticeId,
                };

                this.db.Appointments.AddObject(appointment);
                this.db.SaveChanges();
            }
            catch
            {
                Assert.Inconclusive("Test initialization has failed.");
                return;
            }

            controller.Delete(patient.Id);

            // this patient must have been deleted
            patient = this.db.Patients.FirstOrDefault(p => p.Id == patient.Id);
            Assert.IsNull(patient);
        }
        public void Create_SaveAppointmentConflictingWithAnother_HappyPath()
        {
            ScheduleController controller;
            var isDbChanged = false;
            AppointmentViewModel vm;

            // Dates that will be used by this test.
            // - utcNow and localNow: used to mock Now values from Utc and User point of view.
            // - start and end: start and end time of the appointments that will be created.
            DateTime utcStart, utcEnd;
            var localNow = new DateTime(2012, 07, 19, 12, 00, 00, 000);

            // Setting Now to be on an thursday, mid day.
            // We know that Dr. House works only after 13:00, so we need to set appointments after that.
            // 28 days from now in the future.
            var start = localNow.Date.AddDays(28).AddHours(13); // 2012-07-19 13:00
            var end = start.AddMinutes(30); // 2012-07-19 13:30

            try
            {
                // Creating practice and doctor.
                var docAndre = Firestarter.Create_CrmMg_Psiquiatria_DrHouse_Andre(this.db);
                Firestarter.SetupDoctor(docAndre, this.db);

                var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(docAndre.Users.Single().Practice.WindowsTimeZoneId);
                var utcNow = TimeZoneInfo.ConvertTimeToUtc(localNow, timeZoneInfo);
                utcStart = TimeZoneInfo.ConvertTimeToUtc(start, timeZoneInfo);
                utcEnd = TimeZoneInfo.ConvertTimeToUtc(end, timeZoneInfo);

                // Creating an appointment.
                var appointment = new Appointment
                    {
                        CreatedBy = docAndre.Users.Single(),
                        CreatedOn = utcNow,
                        Description = "This is a generic appointment.",
                        Doctor = docAndre,
                        Start = utcStart,
                        End = utcEnd,
                        Type = (int)TypeAppointment.GenericAppointment,
                        HealthInsuranceId = docAndre.HealthInsurances.First(hi => hi.IsActive).Id,
                        PracticeId = docAndre.PracticeId,
                    };
                this.db.Appointments.AddObject(appointment);
                this.db.SaveChanges();

                // Creating Asp.Net Mvc mocks.
                var mr = new MockRepository(true);
                mr.SetRouteData_ConsultorioDrHouse_GregoryHouse(typeof(ScheduleController), "Create");

                controller = mr.CreateController<ScheduleController>(
                    setupNewDb: db2 => db2.SavingChanges += (s, e) => { isDbChanged = true; });

                controller.UtcNowGetter = () => utcNow;

                // Setting view-model values to create a new appointment.
                // - this view-model must be valid for this test... if some day it becomes invalid,
                //   then it must be made valid again.
                vm = new AppointmentViewModel
                    {
                        Description = "Another generic appointment.",
                        LocalDateTime = start.Date,
                        DoctorId = docAndre.Id,
                        Start = start.ToString("HH:mm"),
                        End = end.ToString("HH:mm"),
                        IsGenericAppointment = true,
                        HealthInsuranceId = docAndre.HealthInsurances.First(hi => hi.IsActive).Id,
                    };

                Mvc3TestHelper.SetModelStateErrors(controller, vm);

                if (!controller.ModelState.IsValid)
                    throw new Exception("The given view-model must be valid for this test.");
            }
            catch (Exception ex)
            {
                InconclusiveInit(ex);
                return;
            }

            // View new appointment.
            // This must be ok, no exceptions, no validation errors.
            ActionResult actionResult;

            {
                actionResult = controller.Create(vm);
            }

            // Verifying the ActionResult.
            Assert.IsNotNull(actionResult, "The result of the controller method is null.");
            Assert.IsInstanceOfType(actionResult, typeof(JsonResult));
            var jsonResult = (JsonResult)actionResult;
            Assert.AreEqual("success", ((dynamic)jsonResult.Data).status);

            // Verifying the view-model.
            // todo: this should verify a mocked message, but cannot mock messages until languages are implemented.
            Assert.AreEqual(
                "A data e hora já está marcada para outro compromisso.",
                vm.TimeValidationMessage);
            Assert.AreEqual(DateAndTimeValidationState.Warning, vm.DateAndTimeValidationState);

            // Verifying the controller.
            Assert.AreEqual(controller.ViewBag.IsEditingOrCreating, null); // when JsonResult there must be no ViewBag
            Assert.IsTrue(controller.ModelState.IsValid, "ModelState is not valid.");

            // Verifying the DB.
            Assert.IsTrue(isDbChanged, "Create actions must change DB.");
            using (var db2 = DbTestBase.CreateNewCerebelloEntities())
            {
                int appointmentsCountAtSameTime = db2.Appointments
                    .Where(a => a.Start == utcStart)
                    .Count(a => a.End == utcEnd);

                Assert.AreEqual(2, appointmentsCountAtSameTime);
            }
        }
        public void Delete_HappyPath()
        {
            ScheduleController controller;
            Appointment appointment;

            try
            {
                // Creating practice and doctor.
                var docAndre = Firestarter.Create_CrmMg_Psiquiatria_DrHouse_Andre(this.db);
                Firestarter.SetupDoctor(docAndre, this.db);

                Firestarter.CreateFakePatients(docAndre, db, 1);
                Patient patient = docAndre.Patients.First();

                var referenceTime = DateTime.UtcNow;
                appointment = new Appointment
                    {
                        Doctor = docAndre,
                        CreatedBy = docAndre.Users.First(),
                        CreatedOn = referenceTime,
                        PatientId = patient.Id,
                        Start = referenceTime,
                        End = referenceTime + TimeSpan.FromMinutes(30),
                        PracticeId = docAndre.PracticeId,
                        HealthInsuranceId = docAndre.HealthInsurances.First(hi => hi.IsActive).Id,
                    };

                this.db.Appointments.AddObject(appointment);
                this.db.SaveChanges();

                // Creating Asp.Net Mvc mocks.
                var mr = new MockRepository(true);
                mr.SetRouteData_ConsultorioDrHouse_GregoryHouse(typeof(ScheduleController), "Create");
                controller = mr.CreateController<ScheduleController>();
            }
            catch (Exception ex)
            {
                InconclusiveInit(ex);
                return;
            }

            controller.Delete(appointment.Id);

            var deletedAppointment = this.db.Appointments.FirstOrDefault(a => a.Id == appointment.Id);
            Assert.IsNull(deletedAppointment);
        }
 /// <summary>
 /// Create a new Appointment object.
 /// </summary>
 /// <param name="id">Initial value of the Id property.</param>
 /// <param name="createdOn">Initial value of the CreatedOn property.</param>
 /// <param name="createdById">Initial value of the CreatedById property.</param>
 /// <param name="doctorId">Initial value of the DoctorId property.</param>
 /// <param name="start">Initial value of the Start property.</param>
 /// <param name="end">Initial value of the End property.</param>
 /// <param name="type">Initial value of the Type property.</param>
 /// <param name="practiceId">Initial value of the PracticeId property.</param>
 /// <param name="status">Initial value of the Status property.</param>
 /// <param name="reminderEmailSent">Initial value of the ReminderEmailSent property.</param>
 /// <param name="notified">Initial value of the Notified property.</param>
 public static Appointment CreateAppointment(global::System.Int32 id, global::System.DateTime createdOn, global::System.Int32 createdById, global::System.Int32 doctorId, global::System.DateTime start, global::System.DateTime end, global::System.Int32 type, global::System.Int32 practiceId, global::System.Int32 status, global::System.Boolean reminderEmailSent, global::System.Boolean notified)
 {
     Appointment appointment = new Appointment();
     appointment.Id = id;
     appointment.CreatedOn = createdOn;
     appointment.CreatedById = createdById;
     appointment.DoctorId = doctorId;
     appointment.Start = start;
     appointment.End = end;
     appointment.Type = type;
     appointment.PracticeId = practiceId;
     appointment.Status = status;
     appointment.ReminderEmailSent = reminderEmailSent;
     appointment.Notified = notified;
     return appointment;
 }
 /// <summary>
 /// Deprecated Method for adding a new object to the Appointments EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
 /// </summary>
 public void AddToAppointments(Appointment appointment)
 {
     base.AddObject("Appointments", appointment);
 }