コード例 #1
0
ファイル: BallotModelCore.cs プロジェクト: glittle/TallyJ-3.0
        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
        }
コード例 #2
0
ファイル: LocationModel.cs プロジェクト: glittle/TallyJ-3.0
        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));
        }
コード例 #3
0
        /// <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 = "&nbsp;", VotingMethod = "BLANK"
                });
                numBlanksBefore--;
            }
            var       offset          = 0;
            const int firstBlankAfter = -100;

            while (numBlanksAfter > 0)
            {
                after.Add(new Person {
                    C_RowId = firstBlankAfter + offset++, LastName = "&nbsp;", 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
            }));
        }
コード例 #4
0
        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());
        }
コード例 #5
0
ファイル: BallotModelCore.cs プロジェクト: glittle/TallyJ-3.0
        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);
        }
コード例 #6
0
ファイル: BallotModelCore.cs プロジェクト: glittle/TallyJ-3.0
        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());
        }
コード例 #7
0
ファイル: ElectionModel.cs プロジェクト: glittle/TallyJ-3.0
        /// <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());
        }
コード例 #8
0
ファイル: ComputerModel.cs プロジェクト: glittle/TallyJ-3.0
        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);
        }
コード例 #9
0
        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());
        }