/// <summary> /// Creates a new instance of a OpeningAnswer object, and initializes it with the specified property values. /// </summary> /// <param name="openingQuestion"></param> /// <param name="openingParticipant"></param> /// <param name="answer"></param> public OpeningAnswer(OpeningQuestion openingQuestion, OpeningParticipant openingParticipant, string answer) { if (String.IsNullOrWhiteSpace(answer)) { throw new ArgumentException("The argument 'answer' cannot be null, empty or whitespace."); } this.QuestionId = openingQuestion?.QuestionId ?? throw new ArgumentNullException(nameof(openingQuestion)); this.Question = openingQuestion.Question; this.OpeningId = openingQuestion?.OpeningId ?? throw new ArgumentNullException(nameof(openingQuestion)); this.Opening = openingQuestion.Opening; this.OpeningQuestion = openingQuestion; this.ParticipantId = openingParticipant?.ParticipantId ?? throw new ArgumentNullException(nameof(openingParticipant)); this.Participant = openingParticipant.Participant; this.OpeningParticipant = openingParticipant; this.Text = answer; }
/// <summary> /// The participant is apply for the opening. /// </summary> /// <param name="opening"></param> /// <param name="participant"></param> /// <param name="answers"></param> /// <returns></returns> private Models.Opening Apply(Entities.Opening opening, Entities.Participant participant, params Models.Answer[] answers) { var userId = this.GetUserId(); var participantCount = opening.Participants.Count(p => p.State == OpeningApplicationState.Accepted); if (opening.MaxParticipants <= participantCount) { throw new InvalidOperationException($"The opening has been filled, {participantCount} of {opening.MaxParticipants} applications have been accepted."); } if (opening.Participants.Any(p => p.ParticipantId == participant.Id)) { throw new InvalidOperationException($"Cannot apply for the same opening more than once."); } var openingCriteria = opening.Criteria.ToArray().Select(c => (Criteria)c.Criteria); var activityCriteria = this.Context.ActivityCriteria.Include(ac => ac.Criteria).Where(ac => ac.ActivityId == opening.ActivityId).ToArray().Select(ac => (Criteria)ac.Criteria); var eventCriteria = this.Context.EventCriteria.Include(ec => ec.Criteria).Where(ec => ec.EventId == opening.Activity.EventId).ToArray().Select(ac => (Criteria)ac.Criteria); var calendarCriteria = this.Context.CalendarCriteria.Include(cc => cc.Criteria).Where(cc => cc.CalendarId == opening.Activity.Event.CalendarId).ToArray().Select(ac => (Criteria)ac.Criteria); var criteria = openingCriteria.Concat(activityCriteria).Concat(eventCriteria).Concat(calendarCriteria); // Validate criteria if (!criteria.All(c => c.Validate(participant.Attributes.Select(a => a.Attribute).ToArray()))) { throw new InvalidOperationException($"The participant '{participant.DisplayName}' does not have the required attributes to apply to this opening."); } // Validate questions var answeredQuestionIds = answers?.Select(a => a.QuestionId).ToArray() ?? new int[0]; var hasAnsweredQuestions = opening.Questions.All(q => q.Question.IsRequired && answeredQuestionIds.Contains(q.QuestionId)); if (!hasAnsweredQuestions) { throw new InvalidOperationException($"The application is missing an answer to a question."); } var state = opening.ApplicationProcess == ApplicationProcess.Review ? OpeningApplicationState.Applied : OpeningApplicationState.Accepted; var op = new OpeningParticipant(opening, participant, state) { AddedById = userId }; var eanswers = answers?.Select(a => new OpeningAnswer() { OpeningId = opening.Id, QuestionId = a.QuestionId, ParticipantId = participant.Id, OpeningParticipant = op, Text = a.Text, AddedById = userId }).ToArray() ?? new OpeningAnswer[0]; // TODO: Save answer options. eanswers.ForEach(a => op.Answers.Add(a)); opening.Participants.Add(op); this.Context.OpeningParticipants.Add(op); PerformAction(op, ActionTrigger.Apply); if (opening.ApplicationProcess == ApplicationProcess.AutoAccept) { PerformAction(op, ActionTrigger.Accept); } var result = this.Map(opening); Track(opening, result); return(result); }