public ActionResult Edit(UserViewModel formModel) { var isEditingOrCreating = formModel.Id != null ? 'E' : 'C'; this.ViewBag.IsEditingOrCreating = isEditingOrCreating; var utcNow = this.GetUtcNow(); User user; // Normalizing the name of the person. if (!string.IsNullOrEmpty(formModel.FullName)) { formModel.FullName = Regex.Replace(formModel.FullName, @"\s+", " ").Trim(); } if (isEditingOrCreating == 'E') { // Note: User name cannot be edited, and should not be validated. this.ModelState.ClearPropertyErrors(() => formModel.UserName); user = this.db.Users.First(p => p.Id == formModel.Id); // TODO: suggest that r# use the attribute EdmScalarPropertyAttribute(IsNullable=false) // as a way to determine if a property can ever receive a null value or not // there was a bug in the line inside the following if, that could be detected by r# if it did consider that attribute. if (!string.IsNullOrWhiteSpace(formModel.FullName)) { user.Person.FullName = formModel.FullName; } user.Person.Gender = (short)formModel.Gender; // If there are model errors, we must return original user name to the view. formModel.UserName = user.UserName; } else { // UserName must not be null nor empty. if (string.IsNullOrWhiteSpace(formModel.UserName)) { this.ModelState.AddModelError(() => formModel.UserName, "Nome de usuário inválido."); } var loggedUser = this.DbUser; // Checking doctors limit of this account. if (formModel.IsDoctor) { var doctorsCount = this.DbPractice.Users.Count(u => u.DoctorId != null); if (doctorsCount >= this.DbPractice.AccountContract.DoctorsLimit) { this.ModelState.AddModelError( "DoctorsLimit", "Essa conta está configurada para suportar até {0} médicos.", this.DbPractice.AccountContract.DoctorsLimit); } } // Looking for another user with the same UserName or Email. var conflictingData = this.db.Users .Where(u => u.PracticeId == loggedUser.PracticeId) .Where(u => u.UserName == formModel.UserName || u.Person.Email == formModel.Email) .Select(u => new { u.UserName, u.Person.Email }) .ToList(); // Verifying wich fields are conflicting: Email. #warning [Validate] Must validate all emails. bool emailConflict = conflictingData.Any(c => c.Email == formModel.Email); // For every new user we must create a login, with a common // password used the first time the person logs in. // The only action allowed with this password, // is to change the password. var userData = new CreateAccountViewModel { UserName = formModel.UserName, Password = Constants.DEFAULT_PASSWORD, ConfirmPassword = Constants.DEFAULT_PASSWORD, EMail = formModel.Email, FullName = formModel.FullName, Gender = (short)formModel.Gender, }; // Creating the new user. // The user belongs to the same practice as the logged user. var result = SecurityManager.CreateUser(out user, userData, this.db.Users, utcNow, loggedUser.PracticeId); if (result == CreateUserResult.UserNameAlreadyInUse) { this.ModelState.AddModelError( () => formModel.UserName, // Todo: this message is also used in the AuthenticationController. "O nome de usuário não pode ser registrado pois já está em uso. " + "Note que nomes de usuário diferenciados por acentos, " + "maiúsculas/minúsculas ou por '.', '-' ou '_' não são permitidos." + "(Não é possível cadastrar 'MiguelAngelo' e 'miguel.angelo' no mesmo consultório."); } } #warning Must validade all emails, cannot repeat emails in the same practice. if (!formModel.IsDoctor && !formModel.IsAdministrador && !formModel.IsSecretary) { this.ModelState.AddModelError("", "Usuário tem que ter pelo menos uma função: médico, administrador ou secretária."); } // If the user being edited is a doctor, then we must check the fields that are required for medics. if (!formModel.IsDoctor) { // Removing validation error of medic properties, because this user is not a medic. this.ModelState.ClearPropertyErrors(() => formModel.MedicCRM); this.ModelState.ClearPropertyErrors(() => formModel.MedicalEntityId); this.ModelState.ClearPropertyErrors(() => formModel.MedicalSpecialtyId); this.ModelState.ClearPropertyErrors(() => formModel.MedicalSpecialtyName); this.ModelState.ClearPropertyErrors(() => formModel.MedicalEntityJurisdiction); } if (user != null) { if (formModel.DateOfBirth.HasValue) { user.Person.DateOfBirth = ConvertToUtcDateTime(this.DbPractice, formModel.DateOfBirth.Value); } user.Person.BirthPlace = formModel.BirthPlace; user.Person.CPF = formModel.Cpf; user.Person.CreatedOn = this.GetUtcNow(); user.Person.MaritalStatus = formModel.MaritalStatus; user.Person.Profession = formModel.Profissao; user.Person.Email = formModel.Email; user.Person.EmailGravatarHash = GravatarHelper.GetGravatarHash(formModel.Email); // handle address if (!user.Person.Addresses.Any()) { user.Person.Addresses.Add( new Address { PracticeId = this.DbUser.PracticeId, CEP = formModel.Address.CEP, City = formModel.Address.City, Complement = formModel.Address.Complement, Neighborhood = formModel.Address.Neighborhood, StateProvince = formModel.Address.StateProvince, Street = formModel.Address.Street, }); } // when the user is a doctor, we need to fill the properties of the doctor if (formModel.IsDoctor) { // Only administrators can change the role of an user. if (this.DbUser.AdministratorId != null) { // if user is already a doctor, we just edit the properties // otherwise we create a new doctor instance if (user.Doctor == null) { user.Doctor = new Doctor { PracticeId = this.DbUser.PracticeId, }; BusHelper.FillNewDoctorUtilityBelt(user.Doctor); } } // Changing the doctor's informations. if (!string.IsNullOrWhiteSpace(formModel.MedicCRM)) { user.Doctor.CRM = formModel.MedicCRM; } if (formModel.MedicalEntityId != null) { var me = this.db.SYS_MedicalEntity.First(me1 => me1.Id == formModel.MedicalEntityId); user.Doctor.MedicalEntityCode = me.Code; user.Doctor.MedicalEntityName = me.Name; } if (formModel.MedicalSpecialtyId != null) { var ms = this.db.SYS_MedicalSpecialty.First(ms1 => ms1.Id == formModel.MedicalSpecialtyId); user.Doctor.MedicalSpecialtyCode = ms.Code; user.Doctor.MedicalSpecialtyName = ms.Name; } if (formModel.MedicalEntityJurisdiction != null) { user.Doctor.MedicalEntityJurisdiction = ((TypeEstadoBrasileiro)formModel.MedicalEntityJurisdiction.Value).ToString(); } // Creating an unique UrlIdentifier for this doctor. // This does not consider UrlIdentifier's used by other kinds of objects. string urlId = GetUniqueDoctorUrlId(this.db.Doctors, formModel.FullName, this.DbPractice.Id); if (urlId == null && !string.IsNullOrWhiteSpace(formModel.FullName)) { this.ModelState.AddModelError( () => formModel.FullName, // Todo: this message is also used in the AuthenticationController. string.Format("Quantidade máxima de homônimos excedida para esta conta: {0}.", this.DbPractice.UrlIdentifier)); } if (!string.IsNullOrWhiteSpace(urlId)) { user.Doctor.UrlIdentifier = urlId; } } else { // Only administrators can change the role of an user. if (this.DbUser.AdministratorId != null) { if (user.Doctor != null) { this.db.Doctors.DeleteObject(user.Doctor); } // if the user is not a doctor, then we make sure // by assigning the doctor property to null user.Doctor = null; } } // when the user is an administrator if (formModel.IsAdministrador) { // Only administrators can change the role of an user. if (this.DbUser.AdministratorId != null) { if (user.Administrator == null) { user.Administrator = new Administrator { PracticeId = this.DbUser.PracticeId, } } } ; } else { // Only administrators can change the role of an user. if (this.DbUser.AdministratorId != null) { if (user.Administrator != null) { this.db.Administrators.DeleteObject(user.Administrator); } user.Administrator = null; } } if (user.IsOwner) { if (!formModel.IsAdministrador) { this.ModelState.AddModelError( () => formModel.IsAdministrador, "Não é possível remover o papel de administrador do proprietário da conta."); } } // when the user is a secretary if (formModel.IsSecretary) { // Only administrators can change the role of an user. if (this.DbUser.AdministratorId != null) { if (user.Secretary == null) { user.Secretary = new Secretary { PracticeId = this.DbUser.PracticeId, } } } ; } else { // Only administrators can change the role of an user. if (this.DbUser.AdministratorId != null) { if (user.Secretary != null) { this.db.Secretaries.DeleteObject(user.Secretary); } user.Secretary = null; } } } // If ModelState is still valid, save the objects to the database. if (this.ModelState.IsValid) { if (formModel.Id == null) { var notificationData = new NewUserCreatedNotificationData() { UserName = user.UserName }; var dbNotification = new Notification() { CreatedOn = this.GetUtcNow(), PracticeId = this.DbPractice.Id, UserToId = this.DbUser.Id, Type = NotificationConstants.NEW_USER_NOTIFICATION_TYPE, Data = new JavaScriptSerializer().Serialize(notificationData) }; this.db.Notifications.AddObject(dbNotification); this.db.SaveChanges(); NotificationsHub.BroadcastDbNotification(dbNotification, notificationData); } // Saving all the changes. this.db.SaveChanges(); return(this.RedirectToAction("Details", new { id = user.Id })); } this.ViewBag.MedicalSpecialtyOptions = this.db.SYS_MedicalSpecialty .ToList() .Select(ms => new SelectListItem { Value = ms.Id.ToString(), Text = ms.Name }) .ToList(); this.ViewBag.MedicalEntityOptions = this.db.SYS_MedicalEntity .ToList() .Select(me => new SelectListItem { Value = me.Id.ToString(), Text = me.Name }) .ToList(); if (this.DbUser.AdministratorId != null || this.DbUser.IsOwner) { this.ViewBag.CanEditRole = true; } // Removes all duplicated messages. this.ModelState.RemoveDuplicates(); return(this.View("Edit", formModel)); }