protected Ballot CreateAndRegisterBallot() { var currentLocationGuid = UserSession.CurrentLocationGuid; if (!currentLocationGuid.HasContent()) { var locationModel = new LocationModel(); currentLocationGuid = locationModel.GetLocations_Physical().First().LocationGuid; UserSession.CurrentLocationGuid = currentLocationGuid; } var computerCode = UserSession.CurrentComputerCode; var ballotCacher = new BallotCacher(Db); var firstBallot = ballotCacher.AllForThisElection.Any(); var ballot = new Ballot { BallotGuid = Guid.NewGuid(), LocationGuid = currentLocationGuid, ComputerCode = computerCode, BallotNumAtComputer = NextBallotNumAtComputer(), StatusCode = BallotStatusEnum.Empty, Teller1 = UserSession.GetCurrentTeller(1), Teller2 = UserSession.GetCurrentTeller(2) }; Db.Ballot.Add(ballot); if (firstBallot) { var locationCacher = new LocationCacher(Db); var location = locationCacher.AllForThisElection.FirstOrDefault(l => l.LocationGuid == currentLocationGuid); if (location != null && location.BallotsCollected.AsInt() == 0) { var ballotSources = new PersonCacher(Db) .AllForThisElection .Count(p => !string.IsNullOrEmpty(p.VotingMethod) && p.VotingLocationGuid == currentLocationGuid); location.BallotsCollected = ballotSources; locationCacher.UpdateItemAndSaveCache(location); } } Db.SaveChanges(); ballotCacher.UpdateItemAndSaveCache(ballot); SessionKey.CurrentBallotId.SetInSession(ballot.C_RowId); return(ballot); //TODO: used to be view }
public object CurrentBallotLocationInfo() { //var ballotInfo = BallotModelFactory.GetForCurrentElection().GetCurrentBallotInfo(); //if (ballotInfo == null) //{ // return null; //} //var location = Db.Location.Single(l => l.LocationGuid == ballotInfo.LocationGuid); var currentLocation = UserSession.CurrentLocation; if (currentLocation == null) { currentLocation = new LocationModel().GetLocations_All().First(); } return(LocationInfoForJson(currentLocation)); }
/// <Summary>Only those listed</Summary> public IEnumerable <object> PersonLines(List <Person> people, int numBlanksBefore, int numBlanksAfter, bool includeAbsentees) { var before = new List <Person>(); var after = new List <Person>(); while (numBlanksBefore > 0) { before.Add(new Person { C_RowId = 0 - numBlanksBefore, LastName = " ", VotingMethod = "BLANK" }); numBlanksBefore--; } var offset = 0; const int firstBlankAfter = -100; while (numBlanksAfter > 0) { after.Add(new Person { C_RowId = firstBlankAfter + offset++, LastName = " ", VotingMethod = "BLANK" }); numBlanksAfter--; } var locationModel = new LocationModel(); // var currentElection = UserSession.CurrentElection; var i = 0; return (before.Concat(people .OrderBy(p => p.LastName) .ThenBy(p => p.FirstName)).Concat(after) .Select(p => new { PersonId = p.C_RowId, FullName = p.C_FullName, //.FullNameFL, Area = p.Area, TS = p.C_RowVersionInt, Loc = locationModel.IdFor(p.VotingLocationGuid), Env = p.VotingMethod == VotingMethodEnum.Online ? null : p.EnvNum, VM = p.VotingMethod, Pos = ++i })); }
public override JsonResult StartNewBallotJson() { if (UserSession.CurrentElectionStatus == ElectionTallyStatusEnum.Finalized) { return(new { Message = UserSession.FinalizedNoChangesMessage }.AsJsonResult()); } // for single name, only one ballot per computer var ballots = new BallotCacher(Db).AllForThisElection; if (ballots.Any(b => b.ComputerCode == UserSession.CurrentComputerCode)) { return(new { Message = "Only one 'ballot' per computer in single-name elections." }.AsJsonResult()); } var locationModel = new LocationModel(); if (locationModel.HasMultiplePhysicalLocations && UserSession.CurrentLocation == null) { return(new { Message = "Must select your location first!" }.AsJsonResult()); } if (UserSession.GetCurrentTeller(1).HasNoContent()) { return(new { Message = "Must select \"Teller at Keyboard\" first!" }.AsJsonResult()); } var ballotInfo = CreateAndRegisterBallot(); var allVotes = new VoteCacher(Db).AllForThisElection; return(new { BallotInfo = BallotInfoForJs(ballotInfo, allVotes), Ballots = CurrentBallotsInfoList() }.AsJsonResult()); }
public bool CreateBallotForOnlineVoter(List <OnlineRawVote> poolList, out string errorMessage) { //{Id: 0, First:"", Last:"", OtherInfo:""} // double check var numberToElect = UserSession.CurrentElection.NumberToElect; if (poolList.Count != numberToElect) { errorMessage = $"Invalid number of votes ({poolList.Count}). Need {numberToElect}."; return(false); } var ballotCacher = new BallotCacher(Db); var voteCacher = new VoteCacher(Db); var locationHelper = new LocationModel(Db); var location = locationHelper.GetOnlineLocation(); // create ballot var ballot = new Ballot { BallotGuid = Guid.NewGuid(), LocationGuid = location.LocationGuid, ComputerCode = ComputerModel.ComputerCodeForOnline, BallotNumAtComputer = 0, // maxNum + 1, // will reset later StatusCode = BallotStatusEnum.Empty, }; Db.Ballot.Add(ballot); Db.SaveChanges(); ballotCacher.UpdateItemAndSaveCache(ballot); // add Votes var nextVoteNum = 0; foreach (var rawVote in poolList) { Vote vote; if (rawVote.Id > 0) { var person = new PersonCacher(Db).AllForThisElection.FirstOrDefault(b => b.C_RowId == rawVote.Id); if (person == null) { errorMessage = $"Error converting pool id {rawVote.Id} to person."; return(false); } vote = new Vote { BallotGuid = ballot.BallotGuid, PositionOnBallot = ++nextVoteNum, StatusCode = VoteStatusCode.Ok, PersonGuid = person.PersonGuid, PersonCombinedInfo = person.CombinedInfo, SingleNameElectionCount = 1, // okay if set for normal election too InvalidReasonGuid = person.CanReceiveVotes.AsBoolean(true) ? null : person.IneligibleReasonGuid }; } else { // "random" vote vote = new Vote { BallotGuid = ballot.BallotGuid, PositionOnBallot = ++nextVoteNum, StatusCode = VoteStatusCode.OnlineRaw, SingleNameElectionCount = 1, OnlineVoteRaw = JsonConvert.SerializeObject(rawVote), }; // attempt to match if it is exact... var matched = new PersonCacher(Db).AllForThisElection // match on first and last name only .Where(p => p.FirstName.ToLower() == rawVote.First.ToLower() && p.LastName.ToLower() == rawVote.Last.ToLower()) // don't match if our list has "otherInfo" for this person - there might be some special considerations .Where(p => p.OtherInfo.HasNoContent()) .ToList(); if (matched.Count == 1) { // found one exact match var person = matched[0]; vote.StatusCode = VoteStatusCode.Ok; vote.PersonGuid = person.PersonGuid; vote.PersonCombinedInfo = person.CombinedInfo; vote.InvalidReasonGuid = person.CanReceiveVotes.AsBoolean(true) ? null : person.IneligibleReasonGuid; } } Db.Vote.Add(vote); Db.SaveChanges(); voteCacher.UpdateItemAndSaveCache(vote); } var votes = voteCacher.AllForThisElection; BallotAnalyzerLocal.UpdateBallotStatus(ballot, VoteInfosFor(ballot, votes), true); ballotCacher.UpdateItemAndSaveCache(ballot); Db.SaveChanges(); errorMessage = ""; return(true); }
public JsonResult SaveVote(int personId, int voteId, Guid?invalidReason, int lastVid, int count, bool verifying) { if (UserSession.CurrentElectionStatus == ElectionTallyStatusEnum.Finalized) { return(new { Message = UserSession.FinalizedNoChangesMessage }.AsJsonResult()); } var locationModel = new LocationModel(); if (locationModel.HasMultiplePhysicalLocations && UserSession.CurrentLocation == null) { return(new { Message = "Must select your location first!" }.AsJsonResult()); } if (UserSession.GetCurrentTeller(1).HasNoContent()) { return(new { Message = "Must select \"Teller at Keyboard\" first!" }.AsJsonResult()); } var isSingleName = UserSession.CurrentElection.IsSingleNameElection; var ballot = GetCurrentBallot(); if (ballot == null) { // don't have an active Ballot! return(new { Updated = false, Error = "Invalid ballot" }.AsJsonResult()); } Db.Ballot.Attach(ballot); var voteCacher = new VoteCacher(Db); var personCacher = new PersonCacher(Db); if (voteId != 0) { // update existing record // find info about the existing Vote var vote = voteCacher.AllForThisElection.SingleOrDefault(v => v.C_RowId == voteId); if (vote == null) { // problem... client has a vote number, but we didn't find... return(new { Updated = false, Error = "Invalid vote id" }.AsJsonResult()); } if (vote.BallotGuid != ballot.BallotGuid) { // problem... client is focused on a different ballot! return(new { Updated = false, Error = "Invalid vote/ballot id" }.AsJsonResult()); } Db.Vote.Attach(vote); vote.SingleNameElectionCount = count; var person1 = personCacher.AllForThisElection.SingleOrDefault(p => p.C_RowId == personId); vote.PersonCombinedInfo = person1?.CombinedInfo; if (UserSession.CurrentLocation.IsVirtual) { // changing person on an online ballot if (person1 == null) { vote.PersonGuid = null; } else { vote.PersonGuid = person1.PersonGuid; invalidReason = person1.IneligibleReasonGuid; } vote.StatusCode = invalidReason == null ? VoteStatusCode.Ok : VoteStatusCode.Spoiled; } DetermineInvalidReasonGuid(invalidReason, vote); vote.StatusCode = VoteAnalyzer.DetermineStatus(new VoteInfo(vote, UserSession.CurrentElection, ballot, UserSession.CurrentLocation, person1)); Db.SaveChanges(); var votes = voteCacher.UpdateItemAndSaveCache(vote).AllForThisElection; var ballotStatusInfo = BallotAnalyzerLocal.UpdateBallotStatus(ballot, VoteInfosFor(ballot, votes), true); var sum = _helper.BallotCount(ballot.LocationGuid, isSingleName, null, votes); ballot.Teller1 = UserSession.GetCurrentTeller(1); ballot.Teller2 = UserSession.GetCurrentTeller(2); new BallotCacher(Db).UpdateItemAndSaveCache(ballot); Db.SaveChanges(); var ballotCounts = isSingleName ? new VoteCacher().AllForThisElection .Where(v => v.BallotGuid == ballot.BallotGuid) .Sum(v => v.SingleNameElectionCount) : 0; var ballotCountNames = isSingleName ? new VoteCacher().AllForThisElection .Count(v => v.BallotGuid == ballot.BallotGuid) : 0; return(new { Updated = true, BallotStatus = ballotStatusInfo.Status.Value, BallotStatusText = ballotStatusInfo.Status.DisplayText, ballotStatusInfo.SpoiledCount, LocationBallotsEntered = sum, BallotId = ballot.C_RowId, SingleBallotCount = ballotCounts, SingleBallotNames = ballotCountNames, VoteUpdates = GetVoteUpdates(lastVid, voteCacher, isSingleName, personCacher), LastVid = vote.C_RowId, vote.InvalidReasonGuid, Name = person1?.C_FullName, person1?.Area, vote = CurrentVotesForJs(GetCurrentBallot(), new List <Vote> { vote }).First() }.AsJsonResult()); } // make a new Vote record var location = new LocationCacher(Db).AllForThisElection.Single(l => l.LocationGuid == ballot.LocationGuid); if (location.IsVirtual) { return(new { Updated = false, Error = "Cannot add votes to an online ballot" }.AsJsonResult()); } var invalidReasonGuid = DetermineInvalidReasonGuid(invalidReason); var person = personCacher.AllForThisElection.SingleOrDefault(p => p.C_RowId == personId); var ok = person != null || (invalidReason != null && invalidReasonGuid != Guid.Empty); if (ok) { var nextVoteNum = 1 + voteCacher.AllForThisElection.Where(v => v.BallotGuid == ballot.BallotGuid) .OrderByDescending(v => v.PositionOnBallot) .Take(1) .Select(b => b.PositionOnBallot) .SingleOrDefault(); var vote = new Vote { BallotGuid = ballot.BallotGuid, PositionOnBallot = nextVoteNum, StatusCode = VoteStatusCode.Ok, SingleNameElectionCount = count }; if (person != null) { vote.PersonGuid = person.PersonGuid; vote.PersonCombinedInfo = person.CombinedInfo; vote.InvalidReasonGuid = person.CanReceiveVotes.AsBoolean(true) ? null : person.IneligibleReasonGuid; // VoteHelperLocal.IneligibleToReceiveVotes(person.IneligibleReasonGuid, // person.CanReceiveVotes); } vote.InvalidReasonGuid = invalidReasonGuid; Db.Vote.Add(vote); Db.SaveChanges(); var votes = voteCacher.UpdateItemAndSaveCache(vote).AllForThisElection; var rawBallot = CurrentRawBallot(); var ballotStatusInfo = BallotAnalyzerLocal.UpdateBallotStatus(rawBallot, VoteInfosFor(rawBallot, votes), true); var sum = _helper.BallotCount(ballot.LocationGuid, isSingleName, null, votes); new BallotCacher(Db).UpdateItemAndSaveCache(rawBallot); Db.SaveChanges(); var ballotCounts = isSingleName ? new VoteCacher().AllForThisElection .Where(v => v.BallotGuid == ballot.BallotGuid) .Sum(v => v.SingleNameElectionCount) : 0; var ballotCountNames = isSingleName ? new VoteCacher().AllForThisElection .Count(v => v.BallotGuid == ballot.BallotGuid) : 0; return(new { Updated = true, VoteId = vote.C_RowId, pos = vote.PositionOnBallot, BallotStatus = ballotStatusInfo.Status.Value, BallotStatusText = ballotStatusInfo.Status.DisplayText, ballotStatusInfo.SpoiledCount, BallotId = ballot.C_RowId, LocationBallotsEntered = sum, SingleBallotCount = ballotCounts, SingleBallotNames = ballotCountNames, VoteUpdates = GetVoteUpdates(lastVid, voteCacher, isSingleName, personCacher), LastVid = vote.C_RowId }.AsJsonResult()); } // don't recognize person id return(new { Updated = false, Error = "Invalid person. Please try again." }.AsJsonResult()); }
/// <Summary>Gets directly from the database, not session. Stores in session.</Summary> /// <Summary>Saves changes to this election</Summary> public JsonResult SaveElection(Election electionFromBrowser) { var electionCacher = new ElectionCacher(Db); var election = UserSession.CurrentElection; Db.Election.Attach(election); var beforeChanges = election.GetAllProperties(); var currentType = election.ElectionType; var currentMode = election.ElectionMode; var currentNum = election.NumberToElect; // var currentCan = election.CanVote; // var currentReceive = election.CanReceive; var currentListed = election.ListForPublic; // List of fields to allow edit from setup page var editableFields = new { election.Name, election.DateOfElection, election.Convenor, election.ElectionType, election.ElectionMode, election.NumberToElect, election.NumberExtra, // election.CanVote, // election.CanReceive, election.ListForPublic, election.ShowAsTest, election.ElectionPasscode, //election.UseCallInButton, - use VotingMethods now election.HidePreBallotPages, election.MaskVotingMethod, election.BallotProcessRaw, election.EnvNumModeRaw, election.T24, election.OnlineWhenOpen, election.OnlineWhenClose, election.OnlineCloseIsEstimate, election.OnlineSelectionProcess, election.EmailFromAddress, election.EmailFromName, election.VotingMethods, election.CustomMethods, }.GetAllPropertyInfos().Select(pi => pi.Name).ToList(); // if (election.ElectionType == ElectionTypeEnum.Oth) // { // editableFields.Add(election.CanVote); // editableFields.Add(election.CanReceive); // } if (!currentListed.AsBoolean() && election.ListForPublic.AsBoolean()) { // just turned on election.ListedForPublicAsOf = DateTime.Now; } var changed = electionFromBrowser.CopyPropertyValuesTo(election, editableFields); var coreSettingsChanged = currentMode != election.ElectionMode || currentType != election.ElectionType || currentNum != election.NumberToElect; // || currentCan != election.CanVote // || currentReceive != election.CanReceive; if (coreSettingsChanged) { var setupModel = new SetupModel(); if (setupModel.HasBallots || setupModel.HasOnlineBallots) { return(new { success = false, Status = "Cannot change type of election after ballots are entered." }.AsJsonResult()); } } var locationModel = new LocationModel(); var onlineLocation = locationModel.GetOnlineLocation(); if (changed) { // check if trying to turn off online elections if (!election.OnlineEnabled) { if (onlineLocation != null) { if (locationModel.IsLocationInUse(onlineLocation.LocationGuid)) { beforeChanges.CopyPropertyValuesTo(election); // we have ballots from Online... can't remove Open date! return(new { success = false, Status = "Online ballots received. Cannot disable online voting.", Election = election, displayName = UserSession.CurrentElectionDisplayNameAndInfo }.AsJsonResult()); } } } Db.SaveChanges(); electionCacher.UpdateItemAndSaveCache(election); new PublicHub() .TellPublicAboutVisibleElections(); // in case the name, or ListForPublic, etc. has changed } if (coreSettingsChanged) { // reset flags // new PeopleModel().SetInvolvementFlagsToDefault(); --> must re-import list to apply settings to everyone // update analysis new ResultsModel().GenerateResults(); } // adjust for Online if (election.OnlineEnabled) { if (onlineLocation == null) { // need a new location for online! locationModel.EditLocation(0, LocationModel.OnlineLocationName, true); } } else { // not enabled if (onlineLocation != null) { // remove it (already checked that it is not in use) locationModel.EditLocation(onlineLocation.C_RowId, "", true); } } new AllVotersHub() .UpdateVoters(new { changed = true, election.OnlineWhenClose, election.OnlineWhenOpen, election.OnlineCloseIsEstimate, election.OnlineSelectionProcess }); new FrontDeskHub() .UpdateOnlineElection(new { election.OnlineWhenClose, election.OnlineWhenOpen, election.OnlineCloseIsEstimate, }); // alert will go out when the scheduled job runs return(new { success = true, Status = "Saved", defaultFromAddress = UserSession.CurrentElection.EmailFromAddressWithDefault, Election = election, displayName = UserSession.CurrentElectionDisplayNameAndInfo }.AsJsonResult()); }
public Computer GetComputerForMe(Guid oldComputerGuid) { Computer computer; var computerCacher = new ComputerCacher(); var locationGuid = UserSession.CurrentLocationGuid; var locationModel = new LocationModel(); var hasMultiplePhysicalLocations = locationModel.HasMultiplePhysicalLocations; if (locationGuid == Guid.Empty && !hasMultiplePhysicalLocations) { // if only one location, learn what it is var locations = locationModel.GetLocations_Physical(); // var locations = new LocationCacher(Db) // .AllForThisElection // .Where(l => l.Name != LocationModel.OnlineLocationName) // .Where(l => l.Name != LocationModel.ImportedLocationName) // .OrderBy(l => l.SortOrder).ToList(); if (locations.Count == 0) { // missing location? fix it var location = new Location { ElectionGuid = UserSession.CurrentElectionGuid, Name = "Main Location", LocationGuid = Guid.NewGuid() }; Db.Location.Add(location); Db.SaveChanges(); locationGuid = location.LocationGuid; } else { locationGuid = locations.First().LocationGuid; } UserSession.CurrentLocationGuid = locationGuid; } lock (ComputerModelLock) { var allComputersInThisElection = computerCacher.AllForThisElection; computer = allComputersInThisElection.FirstOrDefault(c => c.ComputerGuid == oldComputerGuid && c.ElectionGuid == UserSession.CurrentElectionGuid); if (computer == null) { computer = new Computer { ComputerGuid = Guid.NewGuid(), ComputerCode = DetermineNextFreeComputerCode(allComputersInThisElection.Select(c => c.ComputerCode).Distinct().OrderBy(s => s)), ElectionGuid = UserSession.CurrentElectionGuid }; computerCacher.UpdateComputer(computer); } computer.LastContact = DateTime.Now; computer.LocationGuid = locationGuid; computer.AuthLevel = UserSession.AuthLevel; computer.SessionId = HttpContext.Current.Session.SessionID; } UserSession.CurrentComputer = computer; return(computer); }
public JsonResult RegisterVotingMethod(int personId, string voteType, bool forceDeselect, int locationId) { if (UserSession.CurrentElectionStatus == ElectionTallyStatusEnum.Finalized) { return(new { Message = UserSession.FinalizedNoChangesMessage }.AsJsonResult()); } var locationModel = new LocationModel(); var hasMultiplePhysicalLocations = locationModel.HasMultiplePhysicalLocations; if (hasMultiplePhysicalLocations && UserSession.CurrentLocation == null) { return(new { Message = "Must select your location first!" }.AsJsonResult()); } if (UserSession.CurrentLocation.C_RowId != locationId) { new ComputerModel().MoveCurrentComputerIntoLocation(locationId); } if (UserSession.GetCurrentTeller(1).HasNoContent()) { return(new { Message = "Must select \"Teller at Keyboard\" first!" }.AsJsonResult()); } if (!VotingMethodEnum.Exists(voteType)) { return(new { Message = "Invalid type" }.AsJsonResult()); } var personCacher = new PersonCacher(Db); var person = personCacher.AllForThisElection.SingleOrDefault(p => p.C_RowId == personId); if (person == null) { return(new { Message = "Unknown person" }.AsJsonResult()); } if (person.VotingMethod == VotingMethodEnum.Online) { var onlineVoter = Db.OnlineVotingInfo.SingleOrDefault(ovi => ovi.PersonGuid == person.PersonGuid && ovi.ElectionGuid == person.ElectionGuid); if (onlineVoter != null) { if (onlineVoter.Status == OnlineBallotStatusEnum.Processed) { return(new { Message = "This online ballot has been processed. Registration cannot be changed." }.AsJsonResult()); } } } Db.Person.Attach(person); person.Teller1 = UserSession.GetCurrentTeller(1); person.Teller2 = UserSession.GetCurrentTeller(2); var votingMethodRemoved = false; Guid?oldVoteLocationGuid = null; Guid?newVoteLocationGuid = null; if (person.VotingMethod == voteType || forceDeselect || !person.CanVote.AsBoolean()) { oldVoteLocationGuid = person.VotingLocationGuid; // it is already set this way...turn if off person.VotingMethod = null; person.VotingLocationGuid = null; person.RegistrationTime = DateTime.Now; votingMethodRemoved = true; var log = person.RegistrationLog; log.Add(new[] { ShowRegistrationTime(person), "De-selected", ShowTellers(person), hasMultiplePhysicalLocations ? LocationName(UserSession.CurrentLocationGuid) : null, }.JoinedAsString("; ", true)); person.RegistrationLog = log; } else { person.VotingMethod = voteType; oldVoteLocationGuid = person.VotingLocationGuid; person.VotingLocationGuid = UserSession.CurrentLocationGuid; person.RegistrationTime = DateTime.Now; newVoteLocationGuid = person.VotingLocationGuid; var log = person.RegistrationLog; log.Add(new[] { ShowRegistrationTime(person), VotingMethodEnum.TextFor(person.VotingMethod), ShowTellers(person), hasMultiplePhysicalLocations ? LocationName(UserSession.CurrentLocationGuid) : null, }.JoinedAsString("; ", true)); person.RegistrationLog = log; // make number for every method except Registered var needEnvNum = person.EnvNum == null && voteType != VotingMethodEnum.Registered; if (needEnvNum) { person.EnvNum = new ElectionModel().GetNextEnvelopeNumber(); } } personCacher.UpdateItemAndSaveCache(person); UpdateFrontDeskListing(person, votingMethodRemoved); // if (lastRowVersion == 0) // { // lastRowVersion = person.C_RowVersionInt.AsLong() - 1; // } UpdateLocationCounts(newVoteLocationGuid, oldVoteLocationGuid, personCacher); Db.SaveChanges(); return(true.AsJsonResult()); }