public EditInvitationCommandValidator(IInvitationValidator invitationValidator, IRowVersionValidator rowVersionValidator)
        {
            CascadeMode = CascadeMode.Stop;

            RuleFor(command => command)
            //input validators
            .Must(command => command.UpdatedParticipants != null)
            .WithMessage("Participants cannot be null!")
            .Must(command => command.Description == null || command.Description.Length < Invitation.DescriptionMaxLength)
            .WithMessage(command =>
                         $"Description cannot be more than {Invitation.DescriptionMaxLength} characters! Description={command.Description}")
            .Must(command => command.Location == null || command.Location.Length < Invitation.LocationMaxLength)
            .WithMessage(command =>
                         $"Location cannot be more than {Invitation.LocationMaxLength} characters! Location={command.Location}")
            .Must(command => command.StartTime < command.EndTime)
            .WithMessage(command =>
                         $"Start time must be before end time! Start={command.StartTime} End={command.EndTime}")
            .Must(command =>
                  command.Title != null &&
                  command.Title.Length >= Invitation.TitleMinLength &&
                  command.Title.Length < Invitation.TitleMaxLength)
            .WithMessage(command =>
                         $"Title must be between {Invitation.TitleMinLength} and {Invitation.TitleMaxLength} characters! Title={command.Title}")
            //business validators
            .MustAsync((command, cancellationToken) => BeAnExistingIpo(command.InvitationId, cancellationToken))
            .WithMessage(command => $"Invitation with this ID does not exist! Id={command.InvitationId}")
            .MustAsync((command, cancellationToken) => BeAnIpoInPlannedStage(command.InvitationId, cancellationToken))
            .WithMessage(command => $"IPO must be in planned stage to be edited! Id={command.InvitationId}")
            .Must(command => HaveAValidRowVersion(command.RowVersion))
            .WithMessage(command => $"Invitation does not have valid rowVersion! RowVersion={command.RowVersion}")
            .Must(command => MustHaveValidScope(command.Type, command.UpdatedMcPkgScope, command.UpdatedCommPkgScope))
            .WithMessage("Not a valid scope! Choose either DP with mc scope or MDP with comm pkg scope")
            .Must(command => TwoFirstParticipantsMustBeSetWithCorrectOrganization(command.UpdatedParticipants))
            .WithMessage("Contractor and Construction Company must be invited!")
            .Must(command => RequiredParticipantsHaveLowestSortKeys(command.UpdatedParticipants))
            .WithMessage("Contractor must be first and Construction Company must be second!")
            .Must(command => ParticipantListMustBeValid(command.UpdatedParticipants))
            .WithMessage("Each participant must contain an email or oid!");

            RuleForEach(command => command.UpdatedParticipants)
            .MustAsync((command, participant, _, cancellationToken) => ParticipantToBeUpdatedMustExist(participant, command.InvitationId, cancellationToken))
            .WithMessage(_ => $"Participant with ID does not exist on invitation!")
            .Must(participant => participant.SortKey >= 0)
            .WithMessage((_, participant) =>
                         $"Sort key for participant must be a non negative number! SortKey={participant.SortKey}")
            .Must(FunctionalRoleParticipantsMustBeValid)
            .WithMessage((_, participant) =>
                         $"Functional role code must be between 3 and {Participant.FunctionalRoleCodeMaxLength} characters! Code={participant.InvitedFunctionalRole.Code}")
            .Must((command, participant) => ParticipantsHaveValidRowVersions(participant))
            .WithMessage(_ => "Participant doesn't have valid rowVersion!");

            async Task <bool> BeAnExistingIpo(int invitationId, CancellationToken cancellationToken)
            => await invitationValidator.IpoExistsAsync(invitationId, cancellationToken);

            async Task <bool> BeAnIpoInPlannedStage(int invitationId, CancellationToken cancellationToken)
            => await invitationValidator.IpoIsInStageAsync(invitationId, IpoStatus.Planned, cancellationToken);

            bool MustHaveValidScope(
                DisciplineType type,
                IList <string> updatedMcPkgScope,
                IList <string> updatedCommPkgScope)
            => invitationValidator.IsValidScope(type, updatedMcPkgScope, updatedCommPkgScope);

            async Task <bool> ParticipantToBeUpdatedMustExist(ParticipantsForCommand participant, int invitationId, CancellationToken cancellationToken)
            => await invitationValidator.ParticipantWithIdExistsAsync(participant, invitationId, cancellationToken);

            bool TwoFirstParticipantsMustBeSetWithCorrectOrganization(IList <ParticipantsForEditCommand> participants)
            => invitationValidator.RequiredParticipantsMustBeInvited(participants.Cast <ParticipantsForCommand>().ToList());

            bool RequiredParticipantsHaveLowestSortKeys(IList <ParticipantsForEditCommand> participants)
            => invitationValidator.OnlyRequiredParticipantsHaveLowestSortKeys(participants.Cast <ParticipantsForCommand>().ToList());

            bool ParticipantListMustBeValid(IList <ParticipantsForEditCommand> participants)
            => invitationValidator.IsValidParticipantList(participants.Cast <ParticipantsForCommand>().ToList());

            bool HaveAValidRowVersion(string rowVersion)
            => rowVersionValidator.IsValid(rowVersion);

            bool ParticipantsHaveValidRowVersions(ParticipantsForEditCommand participant)
            {
                if (participant.InvitedExternalEmailToEdit?.Id != null)
                {
                    return(rowVersionValidator.IsValid(participant.InvitedExternalEmailToEdit.RowVersion));
                }
                if (participant.InvitedPersonToEdit?.Id != null)
                {
                    return(rowVersionValidator.IsValid(participant.InvitedPersonToEdit.RowVersion));
                }

                if (participant.InvitedFunctionalRoleToEdit != null)
                {
                    if (participant.InvitedFunctionalRoleToEdit.Id != null && !rowVersionValidator.IsValid(participant.InvitedFunctionalRoleToEdit.RowVersion))
                    {
                        return(false);
                    }

                    return(participant.InvitedFunctionalRoleToEdit.EditPersons.All(person => person.Id == null || rowVersionValidator.IsValid(person.RowVersion)));
                }

                return(true);
            }

            bool FunctionalRoleParticipantsMustBeValid(ParticipantsForCommand participant)
            {
                if (participant.InvitedFunctionalRole == null)
                {
                    return(true);
                }

                return(participant.InvitedFunctionalRole.Code != null &&
                       participant.InvitedFunctionalRole.Code.Length > 2 &&
                       participant.InvitedFunctionalRole.Code.Length < Participant.FunctionalRoleCodeMaxLength);
            }
        }
コード例 #2
0
        public CreateInvitationCommandValidator(IInvitationValidator invitationValidator)
        {
            CascadeMode = CascadeMode.Stop;

            RuleFor(command => command)
            //input validators
            .Must(command => command.Participants != null)
            .WithMessage("Participants cannot be null!")
            .Must(command =>
                  command.ProjectName != null &&
                  command.ProjectName.Length >= Invitation.ProjectNameMinLength &&
                  command.ProjectName.Length < Invitation.ProjectNameMaxLength)
            .WithMessage(command =>
                         $"Project name must be between {Invitation.ProjectNameMinLength} and {Invitation.ProjectNameMaxLength} characters! ProjectName={command.ProjectName}")
            .Must(command => command.Description == null || command.Description.Length < Invitation.DescriptionMaxLength)
            .WithMessage(command =>
                         $"Description cannot be more than {Invitation.DescriptionMaxLength} characters! Description={command.Description}")
            .Must(command => command.Location == null || command.Location.Length < Invitation.LocationMaxLength)
            .WithMessage(command =>
                         $"Location cannot be more than {Invitation.LocationMaxLength} characters! Location={command.Location}")
            .Must(command => command.StartTime < command.EndTime)
            .WithMessage(command =>
                         $"Start time must be before end time! Start={command.StartTime} End={command.EndTime}")
            .Must(command =>
                  command.Title != null &&
                  command.Title.Length >= Invitation.TitleMinLength &&
                  command.Title.Length < Invitation.TitleMaxLength)
            .WithMessage(command =>
                         $"Title must be between {Invitation.TitleMinLength} and {Invitation.TitleMaxLength} characters! Title={command.Title}")
            //business validators
            .Must(command => MustHaveValidScope(command.Type, command.McPkgScope, command.CommPkgScope))
            .WithMessage("Not a valid scope! Choose either DP with mc scope or MDP with comm pkg scope")
            .Must(command => TwoFirstParticipantsMustBeSetWithCorrectOrganization(command.Participants))
            .WithMessage("Contractor and Construction Company must be invited!")
            .Must(command => RequiredParticipantsHaveLowestSortKeys(command.Participants))
            .WithMessage("Contractor must be first and Construction Company must be second!")
            .Must(command => ParticipantListMustBeValid(command.Participants))
            .WithMessage("Each participant must contain an email or oid!");

            RuleForEach(command => command.Participants)
            .Must(participant => participant.SortKey >= 0)
            .WithMessage((_, participant) =>
                         $"Sort key for participant must be a non negative number! SortKey={participant.SortKey}")
            .Must(FunctionalRoleParticipantsMustBeValid)
            .WithMessage((_, participant) =>
                         $"Functional role code must be between 3 and {Participant.FunctionalRoleCodeMaxLength} characters! Code={participant.InvitedFunctionalRole.Code}");

            bool MustHaveValidScope(DisciplineType type, IList <string> mcPkgScope, IList <string> commPkgScope)
            => invitationValidator.IsValidScope(type, mcPkgScope, commPkgScope);

            bool TwoFirstParticipantsMustBeSetWithCorrectOrganization(IList <ParticipantsForCommand> participants)
            => invitationValidator.RequiredParticipantsMustBeInvited(participants);

            bool RequiredParticipantsHaveLowestSortKeys(IList <ParticipantsForCommand> participants)
            => invitationValidator.OnlyRequiredParticipantsHaveLowestSortKeys(participants);

            bool ParticipantListMustBeValid(IList <ParticipantsForCommand> participants)
            => invitationValidator.IsValidParticipantList(participants);

            bool FunctionalRoleParticipantsMustBeValid(ParticipantsForCommand participant)
            {
                if (participant.InvitedFunctionalRole == null)
                {
                    return(true);
                }

                return(participant.InvitedFunctionalRole.Code != null &&
                       participant.InvitedFunctionalRole.Code.Length > 2 &&
                       participant.InvitedFunctionalRole.Code.Length < Participant.FunctionalRoleCodeMaxLength);
            }
        }