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"); }
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 ); }
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)); }
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)); }
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); }
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 ); } }
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); }
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); }
/// <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(); } }