/// <summary> /// Mark online ballot as "submitted" or locked. /// </summary> /// <param name="locked"></param> /// <returns></returns> public JsonResult LockPool(bool locked) { var currentElection = UserSession.CurrentElection; var personGuid = UserSession.VoterInElectionPersonGuid; var onlineVotingInfo = Db.OnlineVotingInfo .SingleOrDefault(ovi => ovi.ElectionGuid == currentElection.ElectionGuid && ovi.PersonGuid == personGuid); if (onlineVotingInfo == null) { return(new { Error = "Invalid request" }.AsJsonResult()); } if (onlineVotingInfo.Status == OnlineBallotStatusEnum.Processed) { // already processed... don't do anything return(new { Error = "Ballot already processed" }.AsJsonResult()); } var now = DateTime.Now; if (currentElection.OnlineWhenOpen <= now && currentElection.OnlineWhenClose > now) { var onlineVoteHelper = new OnlineVoteHelper(); var logHelper = new LogHelper(); if (!EncryptionHelper.IsEncrypted(onlineVotingInfo.ListPool)) { // upgrade previous record onlineVoteHelper.SetListPoolEncrypted(onlineVotingInfo); } if (locked) { // ensure we have enough votes var rawPool = onlineVoteHelper.GetDecryptedListPool(onlineVotingInfo, out var errorMessage); if (rawPool == null) { logHelper.Add("LockPool but pool is empty. " + errorMessage, true); return(new { Error = "Pool is empty" }.AsJsonResult()); } if (errorMessage.HasContent()) { logHelper.Add(errorMessage, true); return(new { Error = errorMessage }.AsJsonResult()); } List <OnlineRawVote> completePool; try { completePool = JsonConvert.DeserializeObject <List <OnlineRawVote> >(rawPool); } catch (Exception e) { logHelper.Add("LockPool but pool has invalid JSON. " + e.GetBaseException().Message + "... Start of pool: " + rawPool.Left(30), true); return(new { Error = "Technical error in pool. Please edit and try again." }.AsJsonResult()); } var numVotes = completePool.Count; if (numVotes < currentElection.NumberToElect) { var msg = $"Too few votes ({numVotes})"; logHelper.Add(msg + $" Required ({currentElection.NumberToElect})", true); return(new { Error = msg }.AsJsonResult()); } } onlineVotingInfo.PoolLocked = locked; onlineVotingInfo.Status = locked ? OnlineBallotStatusEnum.Submitted : OnlineBallotStatusEnum.Draft; onlineVotingInfo.HistoryStatus += $";{onlineVotingInfo.Status} ({UserSession.VoterLoginSource})|{now.ToJSON()}".FilledWith(onlineVotingInfo.Status, now.ToJSON()); onlineVotingInfo.WhenStatus = now; var personCacher = new PersonCacher(Db); var person = personCacher.AllForThisElection.SingleOrDefault(p => p.PersonGuid == onlineVotingInfo.PersonGuid); if (person == null) { return(new { Error = "Invalid request (2)" }.AsJsonResult()); } if (!person.CanVote.AsBoolean()) { return(new { Error = "Cannot vote" }.AsJsonResult()); } Db.Person.Attach(person); var peopleModel = new PeopleModel(); var votingMethodRemoved = false; string notificationType = null; person.HasOnlineBallot = locked; if (person.VotingMethod.HasContent() && person.VotingMethod != VotingMethodEnum.Online) { // teller has set. Voter can't change it... } else { if (locked) { person.VotingMethod = VotingMethodEnum.Online; person.RegistrationTime = now; person.VotingLocationGuid = new LocationModel().GetOnlineLocation().LocationGuid; person.EnvNum = null; var log = person.RegistrationLog; log.Add(new[] { peopleModel.ShowRegistrationTime(person, true), UserSession.VoterLoginSource, VotingMethodEnum.TextFor(person.VotingMethod), }.JoinedAsString("; ", true)); person.RegistrationLog = log; // logHelper.Add("Locked ballot"); logHelper.Add("Submitted Ballot", false, UserSession.VoterId); var notificationHelper = new NotificationHelper(); var notificationSent = notificationHelper.SendWhenBallotSubmitted(person, currentElection, out notificationType, out var error); if (!notificationSent) { notificationType = null; } } else { // not online or anywhere person.VotingMethod = null; person.VotingLocationGuid = null; person.EnvNum = null; votingMethodRemoved = true; var log = person.RegistrationLog; person.RegistrationTime = now; // set time so that the log will have it log.Add(new[] { peopleModel.ShowRegistrationTime(person, true), "Cancel Online", }.JoinedAsString("; ", true)); person.RegistrationTime = null; // don't keep it visible person.RegistrationLog = log; // logHelper.Add("Unlocked ballot"); logHelper.Add("Recalled Ballot", false, UserSession.VoterId); } } Db.SaveChanges(); personCacher.UpdateItemAndSaveCache(person); peopleModel.UpdateFrontDeskListing(person, votingMethodRemoved); // okay return(new { success = true, notificationType, person.VotingMethod, ElectionGuid = UserSession.CurrentElectionGuid, person.RegistrationTime, onlineVotingInfo.WhenStatus, onlineVotingInfo.PoolLocked }.AsJsonResult()); } return(new { Error = "Closed" }.AsJsonResult()); }