Пример #1
0
        private static Kind DecideTransitionKind(ElectionStateChange transition)
        {
            // ReSharper disable once PossibleInvalidOperationException (already checked)
            ElectionState precedingState = transition.PreviousState.Value;
            ElectionState targetState    = transition.TargetState;

            if (precedingState == ElectionState.PreNominations && targetState == ElectionState.Nominations)
            {
                return(Kind.NominationsStart);
            }

            if (precedingState == ElectionState.Nominations && targetState == ElectionState.PreVoting)
            {
                return(Kind.NominationsEnd);
            }

            if (precedingState == ElectionState.PreVoting && targetState == ElectionState.Voting)
            {
                return(Kind.VotingStart);
            }

            if (precedingState == ElectionState.Voting && targetState == ElectionState.Closed)
            {
                return(Kind.VotingEnd);
            }

            throw new Exception($"This {nameof(ElectionStateChange)} is not a background one");
        }
Пример #2
0
        public static void RecordNewElection(ElectionStateChange createInfo)
        {
            int electionId = createInfo.Election.Id;

            Logger.Information(
                "{InstigatorUsername} created new {Type} election \"{Name}\"",
                createInfo.InstigatorUsername, createInfo.Election.Type, createInfo.Election.Name, electionId
                );
        }
Пример #3
0
        public ActionResult NewCourseRep(ElectionForm form)
        {
            ModelFieldsAccessibility fieldsInfo = NewDefaultFieldsInfo;

            // Ignore stuff that isn't supposed to be in new election
            fieldsInfo.ReplaceUneditableWithOldValues(form, new ElectionForm());
            this.RemoveIgnoredErrors(fieldsInfo);

            if (ModelState.IsValid)
            {
                Election election = Mapper.Map <Election>(form);
                election.Type = ElectionType.CourseRepresentative;
                election.PositionGenerationInProcess = true;

                ElectionStateChange createChangeInfo = new ElectionStateChange
                {
                    Election           = election,
                    PreviousState      = null,
                    TargetState        = election.State,
                    IsCausedByUser     = true,
                    InstigatorUsername = User.Identity.GetUserId(),
                    CompletedAt        = DateTime.Now
                };

                db.Elections.Add(election);
                db.ElectionStateChanges.Add(createChangeInfo);

                using (DbContextTransaction transaction = db.Database.BeginTransaction())
                {
                    db.SaveChanges();

                    // This needs to be after the first big transaction - otherwise EF gets confused about order of actions
                    election.PopulateAutomaticStateTransitions();
                    db.SaveChanges();

                    transaction.Commit();
                }

                AuditLogManager.RecordNewElection(createChangeInfo);

                // Schedule the job to loop over the DB to generate the positions
                BackgroundJob.Enqueue(() => GeneratePositions.Execute(election.Id, JobCancellationToken.Null));

                return(RedirectToAction("Details", new { id = election.Id }));
            }

            ViewData[FormConstants.FieldsInfoKey] = fieldsInfo;

            return(View(form));
        }
Пример #4
0
        public ActionResult NewCouncil(CouncilElectionForm form)
        {
            ModelFieldsAccessibility fieldsInfo = NewCouncilFieldsInfo;

            // Ignore stuff that isn't supposed to be in new election
            fieldsInfo.ReplaceUneditableWithOldValues(form, new CouncilElectionForm());
            this.RemoveIgnoredErrors(fieldsInfo);

            if (ModelState.IsValid)
            {
                Election election = Mapper.Map <Election>(form);
                election.Type = ElectionType.StudentCouncil;

                CouncilElectionData councilData = Mapper.Map <CouncilElectionData>(form);
                councilData.Election = election;

                ElectionStateChange createChangeInfo = new ElectionStateChange
                {
                    Election           = election,
                    PreviousState      = null,
                    TargetState        = election.State,
                    IsCausedByUser     = true,
                    InstigatorUsername = User.Identity.GetUserId(),
                    CompletedAt        = DateTime.Now
                };

                db.Elections.Add(election);
                db.CouncilElectionData.Add(councilData);
                db.ElectionStateChanges.Add(createChangeInfo);

                using (DbContextTransaction transaction = db.Database.BeginTransaction())
                {
                    db.SaveChanges();

                    // This needs to be after the first big transaction - otherwise EF gets confused about order of actions
                    election.PopulateAutomaticStateTransitions();
                    db.SaveChanges();

                    transaction.Commit();
                }

                AuditLogManager.RecordNewElection(createChangeInfo);

                return(RedirectToAction("Details", new { id = election.Id }));
            }

            ViewData[FormConstants.FieldsInfoKey] = fieldsInfo;

            return(View(form));
        }
Пример #5
0
        private void ChangeStateByUserAndRecord(Election election, ElectionState newState)
        {
            ElectionStateChange stateChange = new ElectionStateChange()
            {
                Election           = election,
                PreviousState      = election.State,
                TargetState        = newState,
                IsCausedByUser     = true,
                InstigatorUsername = User.Identity.GetUserId(),
                CompletedAt        = DateTime.Now
            };

            db.ElectionStateChanges.Add(stateChange);
            election.State = newState;

            AuditLogManager.RecordElectionStateChange(stateChange);
        }
Пример #6
0
        public static void RecordElectionStateChange(ElectionStateChange changeInfo)
        {
            int electionId = changeInfo.Election.Id;

            if (changeInfo.IsCausedByUser)
            {
                Logger.Information(
                    "{InstigatorUsername} changed \"{Name}\" election state from {PreviousState} to {TargetState}",
                    changeInfo.InstigatorUsername, changeInfo.Election.Name, changeInfo.PreviousState,
                    changeInfo.TargetState, electionId
                    );
            }
            else
            {
                Logger.Information(
                    "election \"{Name}\" State changed from {PreviousState} to {TargetState}",
                    changeInfo.Election.Name, changeInfo.PreviousState, changeInfo.TargetState, electionId
                    );
            }
        }
Пример #7
0
        public void Execute(Guid transitionId)
        {
            ElectionStateChange transition = GetTransition(transitionId);

            if (transition.CompletedAt != null)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(transitionId),
                          "This transition is already executed"
                          );
            }

            // We don't need the return, but this does validation which we want (before executing the change)
            DecideTransitionKind(transition);

            transition.Election.State = transition.TargetState;
            transition.CompletedAt    = DateTime.Now;

            _db.SaveChanges();

            AuditLogManager.RecordElectionStateChange(transition);
        }
Пример #8
0
        private ElectionStateChange GetTransition(Guid transitionId)
        {
            ElectionStateChange transition = _db.ElectionStateChanges.Find(transitionId);

            if (transition == null)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(transitionId),
                          "No transition with such id"
                          );
            }

            if (!transition.PreviousState.HasValue)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(transitionId),
                          "This transition does not specify preceding state"
                          );
            }

            return(transition);
        }
Пример #9
0
        /// <summary>
        /// Sends emails that result from a transition such as "nominations started"
        /// </summary>
        /// <param name="transitionId">The ID of ElectionStateChange (which will contain all info about the transition)</param>
        public void SendTransitionEmails(Guid transitionId)
        {
            ElectionStateChange transition = GetTransition(transitionId);

            switch (DecideTransitionKind(transition))
            {
            case Kind.NominationsStart:
                BackgroundJob.Enqueue <ElectionStudentSimpleEmailsJobs>(
                    job => job.SendNominationsStart(transition.Election.Id, JobCancellationToken.Null)
                    );
                break;

            case Kind.NominationsEnd:
                BackgroundJob.Enqueue <ElectionStudentSimpleEmailsJobs>(
                    job => job.SendNominationsEnd(transition.Election.Id, JobCancellationToken.Null)
                    );
                break;

            case Kind.VotingStart:
                if (transition.Election.Type == ElectionType.StudentCouncil)
                {
                    BackgroundJob.Enqueue <ElectionStudentSimpleEmailsJobs>(
                        job => job.SendVotingStart(transition.Election.Id, JobCancellationToken.Null)
                        );
                }

                break;

            case Kind.VotingEnd:
                BackgroundJob.Enqueue <ElectionStudentSimpleEmailsJobs>(
                    job => job.SendVotingEnd(transition.Election.Id, JobCancellationToken.Null)
                    );
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }