public JsonResult VerifyTimeAvailability(string date, string start, string end, int? excludeAppointmentId = null) { if (string.IsNullOrEmpty(date) || string.IsNullOrEmpty(start) || string.IsNullOrEmpty(end)) { return this.Json(new { status = DateAndTimeValidationState.Failed.ToString(), text = "Sem informações suficientes", }, JsonRequestBehavior.AllowGet); } else { var localDateParsed = DateTime.Parse(date).Date; if (localDateParsed.Kind != DateTimeKind.Unspecified) throw new ArgumentException("'date' must be expressed in local practice time-zone.", "date"); AppointmentViewModel viewModel = new AppointmentViewModel { LocalDateTime = localDateParsed, Start = start, End = end, }; this.DoDateAndTimeValidation(viewModel, this.GetPracticeLocalNow(), excludeAppointmentId); return this.Json(new { status = viewModel.DateAndTimeValidationState.ToString(), text = viewModel.TimeValidationMessage, }, JsonRequestBehavior.AllowGet); } }
public ActionResult Edit(int id) { var currentUserPracticeId = this.DbUser.PracticeId; var appointment = this.db.Appointments .Where(a => a.Id == id).FirstOrDefault(a => a.Doctor.Users.FirstOrDefault().PracticeId == currentUserPracticeId); if (appointment == null) { // todo: return new HttpNotFoundResult("A consulta/compromisso não existe."); return this.View("NotFound"); } var localNow = this.GetPracticeLocalNow(); var appointmentLocalStart = ConvertToLocalDateTime(this.DbPractice, appointment.Start); var appointmentLocalEnd = ConvertToLocalDateTime(this.DbPractice, appointment.End); var viewModel = new AppointmentViewModel() { Id = appointment.Id, LocalDateTime = appointmentLocalStart.Date, Start = appointmentLocalStart.ToString("HH:mm"), End = appointmentLocalEnd.ToString("HH:mm"), DoctorId = appointment.DoctorId, LocalDateTimeSpelled = DateTimeHelper.GetDayOfWeekAsString(appointmentLocalStart.Date) + ", " + DateTimeHelper.ConvertToRelative( appointmentLocalStart.Date, localNow, DateTimeHelper.RelativeDateOptions.IncludePrefixes | DateTimeHelper.RelativeDateOptions.IncludeSuffixes | DateTimeHelper.RelativeDateOptions.ReplaceToday | DateTimeHelper.RelativeDateOptions.ReplaceYesterdayAndTomorrow), HealthInsuranceId = appointment.HealthInsuranceId, HealthInsuranceName = this.db.HealthInsurances .Where(hi => hi.Id == appointment.HealthInsuranceId) .Select(hi => hi.Name) .SingleOrDefault(), Status = appointment.Status, }; DoDateAndTimeValidation(viewModel, localNow, id); switch ((TypeAppointment)appointment.Type) { case TypeAppointment.GenericAppointment: viewModel.IsGenericAppointment = true; viewModel.Description = appointment.Description; break; case TypeAppointment.MedicalAppointment: viewModel.IsGenericAppointment = false; viewModel.PatientNameLookup = appointment.Patient.Person.FullName; viewModel.PatientId = appointment.PatientId; break; default: throw new Exception("Unsupported appointment type."); } this.ViewBag.IsEditingOrCreating = 'E'; return this.View("Edit", viewModel); }
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 ActionResult Create(DateTime? date, string start, string end, int? patientId, bool? findNextAvailable) { // Note: remember that all DataTime parameter that comes from the client, are expressed in local practice time-zone. var localNow = this.GetPracticeLocalNow(); if (date != null) { // The behavior for 'start' and 'end' parameters are different // depending on 'findNextAvailable' param, when 'date' is something: // - case false: start must have a valid time value, end is optional. if (findNextAvailable == true) { // When 'start' is not specified, we set it to the begining of the day. if (string.IsNullOrEmpty(start)) start = "00:00"; } else if (string.IsNullOrEmpty(start)) { // If date has something, then start and end must also be null or empty. this.ModelState.AddModelError<AppointmentViewModel>( m => m.LocalDateTime, "Ocorreu um erro nos parâmetros desta página."); return this.View("Edit", new AppointmentViewModel()); } } else { date = localNow; if (string.IsNullOrEmpty(start)) start = localNow.ToString("HH:mm"); } var localDateAlone = date.Value.Date; //var slots = GetDaySlots(dateOnly, this.Doctor); var slotDuration = TimeSpan.FromMinutes(this.Doctor.CFG_Schedule.AppointmentTime); // Getting start date and time. var localStartTime = string.IsNullOrEmpty(start) ? localDateAlone : localDateAlone + DateTimeHelper.GetTimeSpan(start); // todo: just delete code or find a place for it? //FindNearestSlotStartTime(ref start, slots, ref startTime); // Getting end date and time. var localEndTime = string.IsNullOrEmpty(end) ? localStartTime + slotDuration : localDateAlone + DateTimeHelper.GetTimeSpan(end); if (localEndTime - localStartTime < slotDuration) localEndTime = localStartTime + slotDuration; // todo: just delete code or find a place for it? //FindNearestSlotEndTime(ref end, slots, ref endTime); // Find next available time slot. if (findNextAvailable == true) { var doctor = this.Doctor; // Determining the date and time to start scanning for a free time slot. var localStartingFrom = localStartTime; if (localNow > localStartingFrom) localStartingFrom = localNow; // Finding the next available time slot, and setting the startTime and endTime. var slot = FindNextFreeTimeInPracticeLocalTime(this.db, doctor, localStartingFrom); localStartTime = slot.Item1; localEndTime = slot.Item2; } localDateAlone = localStartTime.Date; start = localStartTime.ToString("HH:mm"); end = localEndTime.ToString("HH:mm"); // Creating viewmodel. var viewModel = new AppointmentViewModel(); var patient = this.db.Patients .Where(p => p.Id == patientId) .Select(p => new { p.Code, p.Person.FullName, p.LastUsedHealthInsuranceId }) .FirstOrDefault(); if (patient != null) { viewModel.PatientCode = patient.Code.HasValue ? patient.Code.Value.ToString("D6") : "000000"; viewModel.PatientNameLookup = patient.FullName; viewModel.HealthInsuranceId = patient.LastUsedHealthInsuranceId; viewModel.HealthInsuranceName = this.db.HealthInsurances .Where(hi => hi.Id == patient.LastUsedHealthInsuranceId) .Select(hi => hi.Name) .SingleOrDefault(); viewModel.PatientId = patientId; } else { var currentLastCode = this.db.Patients.Max(p => p.Code); if (!currentLastCode.HasValue) currentLastCode = 0; viewModel.PatientCode = (currentLastCode + 1).Value.ToString("D6"); } viewModel.LocalDateTime = localDateAlone; viewModel.Start = start; viewModel.End = end; viewModel.DoctorId = this.Doctor.Id; viewModel.LocalDateTimeSpelled = DateTimeHelper.GetDayOfWeekAsString(localDateAlone) + ", " + DateTimeHelper.ConvertToRelative( localDateAlone, localNow, DateTimeHelper.RelativeDateOptions.IncludePrefixes | DateTimeHelper.RelativeDateOptions.IncludeSuffixes | DateTimeHelper.RelativeDateOptions.ReplaceToday | DateTimeHelper.RelativeDateOptions.ReplaceYesterdayAndTomorrow); this.DoDateAndTimeValidation(viewModel, localNow, null); this.ModelState.Clear(); this.ViewBag.IsEditingOrCreating = 'C'; return this.View("Edit", viewModel); }
public ActionResult Create(AppointmentViewModel formModel) { return this.Edit(formModel); }
private void DoDateAndTimeValidation(AppointmentViewModel viewModel, DateTime localNow, int? excludeAppointmentId) { if (viewModel.LocalDateTime != viewModel.LocalDateTime.Date) throw new ArgumentException("viewModel.Date must be the date alone, without time data."); var inconsistencyMessages = new ModelStateDictionary(); if (!string.IsNullOrEmpty(viewModel.Start) && !string.IsNullOrEmpty(viewModel.End)) { var startTimeLocal = viewModel.LocalDateTime + DateTimeHelper.GetTimeSpan(viewModel.Start); var endTimeLocal = viewModel.LocalDateTime + DateTimeHelper.GetTimeSpan(viewModel.End); var startTimeUtc = ConvertToUtcDateTime(this.DbPractice, startTimeLocal); var endTimeUtc = ConvertToUtcDateTime(this.DbPractice, endTimeLocal); var isTimeAvailable = IsTimeAvailableUtc(startTimeUtc, endTimeUtc, this.Doctor.Appointments, excludeAppointmentId); if (!isTimeAvailable) { inconsistencyMessages.AddModelError( () => viewModel.LocalDateTime, "A data e hora já está marcada para outro compromisso."); } } // Setting the error message to display near the date and time configurations. var emptyErrors = new ModelErrorCollection(); var errorsList = new List<ModelError>(); errorsList.AddRange(this.ModelState.GetPropertyErrors(() => viewModel.LocalDateTime) ?? emptyErrors); errorsList.AddRange(this.ModelState.GetPropertyErrors(() => viewModel.Start) ?? emptyErrors); errorsList.AddRange(this.ModelState.GetPropertyErrors(() => viewModel.End) ?? emptyErrors); // Flag that tells whether the time and date are valid ot not. viewModel.DateAndTimeValidationState = errorsList.Any() ? DateAndTimeValidationState.Failed : !inconsistencyMessages.IsValid ? DateAndTimeValidationState.Warning : DateAndTimeValidationState.Passed; // Continue filling error list with warnings. errorsList.AddRange(inconsistencyMessages.GetPropertyErrors(() => viewModel.LocalDateTime) ?? emptyErrors); errorsList.AddRange(inconsistencyMessages.GetPropertyErrors(() => viewModel.Start) ?? emptyErrors); errorsList.AddRange(inconsistencyMessages.GetPropertyErrors(() => viewModel.End) ?? emptyErrors); if (errorsList.Any()) { viewModel.TimeValidationMessage = errorsList.First().ErrorMessage; } }
private Tuple<DateTime, DateTime> FindNextFreeValidTimeInPracticeLocalTime(Doctor doctor, DateTime localNow, DateTime localStartingFrom) { var localStartingFrom2 = localStartingFrom; while (true) { var slot = FindNextFreeTimeInPracticeLocalTime(this.db, doctor, localStartingFrom2); var vm = new AppointmentViewModel { LocalDateTime = slot.Item1.Date, Start = slot.Item1.ToString("HH:mm"), End = slot.Item2.ToString("HH:mm"), }; this.DoDateAndTimeValidation(vm, localNow, null); if (vm.DateAndTimeValidationState == DateAndTimeValidationState.Passed) { return slot; } localStartingFrom2 = slot.Item2; } }
public void Create_SaveAppointmentWhenStatusIsSetForTheFuture_NotAccomplished() { ScheduleController controller; AppointmentViewModel vm; try { // Creating practice, doctor and patient. var docAndre = Firestarter.Create_CrmMg_Psiquiatria_DrHouse_Andre(this.db); Firestarter.SetupDoctor(docAndre, this.db); var patient = Firestarter.CreateFakePatients(docAndre, this.db, 1)[0]; patient.LastUsedHealthInsuranceId = null; this.db.SaveChanges(); var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(docAndre.Users.Single().Practice.WindowsTimeZoneId); var localNow = new DateTime(2012, 11, 09, 13, 00, 00, 000); var utcNow = TimeZoneInfo.ConvertTimeToUtc(localNow, timeZoneInfo); // the next free time from "now" var db2 = new CerebelloEntitiesAccessFilterWrapper(this.db); db2.SetCurrentUserById(docAndre.Users.Single().Id); // the reason for this .AddMinutes(1) is that FindNextFreeTimeInPracticeLocalTime returns now, when now is available // but now is not considered future, and I need a date in the future so the Status validation will fail var nextFreeTime = ScheduleController.FindNextFreeTimeInPracticeLocalTime(db2, docAndre, localNow.AddMinutes(1)); // Creating Asp.Net Mvc mocks. var mr = new MockRepository(true); mr.SetRouteData_ConsultorioDrHouse_GregoryHouse(typeof(ScheduleController), "Create"); controller = mr.CreateController<ScheduleController>(); // Mocking 'Now' values. controller.UtcNowGetter = () => utcNow; // Setting view-model values to create a new appointment. vm = new AppointmentViewModel { PatientId = patient.Id, PatientNameLookup = patient.Person.FullName, HealthInsuranceId = docAndre.HealthInsurances.First(hi => hi.IsActive).Id, LocalDateTime = nextFreeTime.Item1.Date, DoctorId = docAndre.Id, Start = nextFreeTime.Item1.ToString("HH:mm"), End = nextFreeTime.Item2.ToString("HH:mm"), IsGenericAppointment = false, // this has to generate an error because the appointment is in the future Status = (int)TypeAppointmentStatus.NotAccomplished, }; Mvc3TestHelper.SetModelStateErrors(controller, vm); } catch (Exception ex) { InconclusiveInit(ex); return; } var result = controller.Create(vm); Assert.IsFalse(controller.ModelState.IsValid); Assert.AreEqual(1, controller.ModelState["Status"].Errors.Count); }
public void Create_SaveAppointmentOnLunch_HappyPath() { ScheduleController controller; bool 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 lunch time is from 12:00 until 13:00. var start = localNow.Date.AddDays(7).AddHours(12); // 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); DateTime utcNow = TimeZoneInfo.ConvertTimeToUtc(localNow, timeZoneInfo); utcStart = TimeZoneInfo.ConvertTimeToUtc(start, timeZoneInfo); utcEnd = TimeZoneInfo.ConvertTimeToUtc(end, timeZoneInfo); // 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 = "Generic appointment on lunch time.", 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 marcada está no horário de almoço do médico.", 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()) { var appointmentsCountAtSameTime = db2.Appointments .Where(a => a.Start == utcStart).Count(a => a.End == utcEnd); Assert.AreEqual(1, appointmentsCountAtSameTime); } }
public void Create_SaveWithEmptyFormModel() { ScheduleController controller; bool isDbChanged = false; AppointmentViewModel vm; 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 lunch time is from 12:00 until 13:00. 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.First().Practice.WindowsTimeZoneId); // Dates that will be used by this test. // - utcNow and localNow: used to mock Now values from Utc and User point of view. var utcNow = TimeZoneInfo.ConvertTimeToUtc(localNow, timeZoneInfo); // 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(); Mvc3TestHelper.SetModelStateErrors(controller, vm); } 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."); // Verifying the view-model. Assert.AreEqual(DateAndTimeValidationState.Failed, vm.DateAndTimeValidationState); // Verifying the controller. Assert.AreEqual(controller.ViewBag.IsEditingOrCreating, 'C'); Assert.IsInstanceOfType(controller.ViewBag.HealthInsuranceSelectItems, typeof(List<SelectListItem>)); Assert.AreEqual(3, ((List<SelectListItem>)controller.ViewBag.HealthInsuranceSelectItems).Count); Assert.IsFalse(controller.ModelState.IsValid, "ModelState should be invalid."); // Verifying the DB. Assert.IsFalse(isDbChanged, "Create actions must not change DB when there is an error."); }
public void Create_SaveAppointment_HappyPath() { ScheduleController controller; bool 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, 11, 09, 13, 00, 00, 000); // We know that Dr. House works only after 13:00, so we need to set appointments after that. var start = localNow.Date.AddDays(+7).AddHours(13); var end = start.AddMinutes(30); Patient patient; try { // Creating practice, doctor and patient. var docAndre = Firestarter.Create_CrmMg_Psiquiatria_DrHouse_Andre(this.db); Firestarter.SetupDoctor(docAndre, this.db); patient = Firestarter.CreateFakePatients(docAndre, this.db, 1)[0]; patient.LastUsedHealthInsuranceId = null; this.db.SaveChanges(); var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(docAndre.Users.Single().Practice.WindowsTimeZoneId); DateTime utcNow = TimeZoneInfo.ConvertTimeToUtc(localNow, timeZoneInfo); utcStart = TimeZoneInfo.ConvertTimeToUtc(start, timeZoneInfo); utcEnd = TimeZoneInfo.ConvertTimeToUtc(end, timeZoneInfo); // 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; }); // Mocking 'Now' values. 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 { PatientId = patient.Id, PatientNameLookup = patient.Person.FullName, HealthInsuranceId = docAndre.HealthInsurances.First(hi => hi.IsActive).Id, LocalDateTime = start.Date, DoctorId = docAndre.Id, Start = start.ToString("HH:mm"), End = end.ToString("HH:mm"), IsGenericAppointment = false, Status = (int)TypeAppointmentStatus.Undefined, }; Mvc3TestHelper.SetModelStateErrors(controller, vm); } 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( null, vm.TimeValidationMessage); Assert.AreEqual(DateAndTimeValidationState.Passed, vm.DateAndTimeValidationState); // Verifying the controller. Assert.IsTrue(controller.ModelState.IsValid, "ModelState is not valid, but should be."); // Verifying the DB. Assert.IsTrue(isDbChanged, "Create actions must change DB."); using (var db2 = DbTestBase.CreateNewCerebelloEntities()) { int appointmentsCountAtSameTime = db2.Appointments .Count(a => a.Start == utcStart && a.End == utcEnd); Assert.AreEqual(1, appointmentsCountAtSameTime); var savedPatient = db2.Patients.Single(p => p.Id == patient.Id); Assert.AreEqual(vm.HealthInsuranceId, savedPatient.LastUsedHealthInsuranceId); var savedAppointment = savedPatient.Appointments.Single(); Assert.AreEqual(vm.HealthInsuranceId, savedAppointment.HealthInsuranceId); } }
public void Create_SaveAppointmentWhenStatusIsSetForThePast_NotAccomplished() { ScheduleController controller; AppointmentViewModel vm; try { // Creating practice, doctor and patient. var docAndre = Firestarter.Create_CrmMg_Psiquiatria_DrHouse_Andre(this.db); Firestarter.SetupDoctor(docAndre, this.db); var patient = Firestarter.CreateFakePatients(docAndre, this.db, 1)[0]; patient.LastUsedHealthInsuranceId = null; this.db.SaveChanges(); var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(docAndre.Users.Single().Practice.WindowsTimeZoneId); var localNow = new DateTime(2012, 11, 09, 13, 00, 00, 000); var utcNow = TimeZoneInfo.ConvertTimeToUtc(localNow, timeZoneInfo); // finds a free time in the past week. var db2 = new CerebelloEntitiesAccessFilterWrapper(this.db); db2.SetCurrentUserById(docAndre.Users.Single().Id); var freeTimeInPastWeek = ScheduleController.FindNextFreeTimeInPracticeLocalTime(db2, docAndre, localNow.AddDays(-7)); // Creating Asp.Net Mvc mocks. var mr = new MockRepository(true); mr.SetRouteData_ConsultorioDrHouse_GregoryHouse(typeof(ScheduleController), "Create"); controller = mr.CreateController<ScheduleController>(); // Mocking 'Now' values. controller.UtcNowGetter = () => utcNow; // Setting view-model values to create a new appointment. vm = new AppointmentViewModel { PatientId = patient.Id, PatientNameLookup = patient.Person.FullName, HealthInsuranceId = docAndre.HealthInsurances.First(hi => hi.IsActive).Id, LocalDateTime = freeTimeInPastWeek.Item1.Date, DoctorId = docAndre.Id, Start = freeTimeInPastWeek.Item1.ToString("HH:mm"), End = freeTimeInPastWeek.Item2.ToString("HH:mm"), IsGenericAppointment = false, // this should work because it's in the past Status = (int)TypeAppointmentStatus.NotAccomplished, }; Mvc3TestHelper.SetModelStateErrors(controller, vm); } catch (Exception ex) { InconclusiveInit(ex); return; } controller.Create(vm); Assert.IsTrue(controller.ModelState.IsValid); }