public UnCompletePunchOutCommandValidator(IInvitationValidator invitationValidator, IRowVersionValidator rowVersionValidator) { CascadeMode = CascadeMode.Stop; RuleFor(command => command) .MustAsync((command, cancellationToken) => BeAnExistingInvitation(command.InvitationId, cancellationToken)) .WithMessage(command => $"Invitation with this ID does not exist! Id={command.InvitationId}") .MustAsync((command, cancellationToken) => BeAnInvitationInCompletedStage(command.InvitationId, cancellationToken)) .WithMessage(command => "Invitation is not in completed stage, and thus cannot be uncompleted!") .Must(command => HaveAValidRowVersion(command.InvitationRowVersion)) .WithMessage(command => $"Invitation row version is not valid! InvitationRowVersion={command.InvitationRowVersion}") .Must(command => HaveAValidRowVersion(command.ParticipantRowVersion)) .WithMessage(command => $"Participant row version is not valid! ParticipantRowVersion={command.ParticipantRowVersion}") .MustAsync((command, cancellationToken) => BeACompleterOnIpo(command.InvitationId, cancellationToken)) .WithMessage(command => "The IPO does not have a contractor assigned to uncomplete the IPO!") .MustAsync((command, cancellationToken) => BeAdminOrThePersonWhoCompleted(command.InvitationId, cancellationToken)) .WithMessage(command => "Person trying to uncomplete is not an admin and not the person who completed the IPO!"); async Task <bool> BeAnExistingInvitation(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoExistsAsync(invitationId, cancellationToken); async Task <bool> BeAnInvitationInCompletedStage(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoIsInStageAsync(invitationId, IpoStatus.Completed, cancellationToken); async Task <bool> BeACompleterOnIpo(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoHasCompleterAsync(invitationId, cancellationToken); async Task <bool> BeAdminOrThePersonWhoCompleted(int invitationId, CancellationToken cancellationToken) => await invitationValidator.CurrentUserIsAdminOrValidCompletorParticipantAsync(invitationId, cancellationToken); bool HaveAValidRowVersion(string rowVersion) => rowVersionValidator.IsValid(rowVersion); }
public SignPunchOutCommandValidator(IInvitationValidator invitationValidator, IRowVersionValidator rowVersionValidator) { CascadeMode = CascadeMode.Stop; RuleFor(command => command) .MustAsync((command, cancellationToken) => BeAnExistingInvitation(command.InvitationId, cancellationToken)) .WithMessage(command => $"Invitation with this ID does not exist! Id={command.InvitationId}") .MustAsync((command, cancellationToken) => BeAnExistingParticipant(command.ParticipantId, command.InvitationId, cancellationToken)) .WithMessage(command => $"Participant with ID does not exist on invitation! Id={command.ParticipantId}") .MustAsync((command, cancellationToken) => BeANonCanceledInvitation(command.InvitationId, cancellationToken)) .WithMessage(command => "Invitation is canceled, and thus cannot be signed!") .Must(command => HaveAValidRowVersion(command.ParticipantRowVersion)) .WithMessage(command => $"Participant row version is not valid! ParticipantRowVersion={command.ParticipantRowVersion}") .MustAsync((command, cancellationToken) => BeASigningParticipantOnIpo(command.InvitationId, command.ParticipantId, cancellationToken)) .WithMessage(command => $"Participant is not assigned to sign this IPO! ParticipantId={command.ParticipantId}") .MustAsync((command, cancellationToken) => BeTheAssignedPersonIfPersonParticipant(command.InvitationId, command.ParticipantId, cancellationToken)) .WithMessage(command => "Person signing is not assigned to sign IPO, or there is not a valid functional role on the IPO!") .MustAsync((command, cancellationToken) => BeUnsignedParticipant(command.ParticipantId, command.InvitationId, cancellationToken)) .WithMessage(command => "Participant is already signed!"); async Task <bool> BeAnExistingInvitation(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoExistsAsync(invitationId, cancellationToken); async Task <bool> BeANonCanceledInvitation(int invitationId, CancellationToken cancellationToken) => !await invitationValidator.IpoIsInStageAsync(invitationId, IpoStatus.Canceled, cancellationToken); async Task <bool> BeASigningParticipantOnIpo(int invitationId, int participantId, CancellationToken cancellationToken) => await invitationValidator.SignerExistsAsync(invitationId, participantId, cancellationToken); async Task <bool> BeTheAssignedPersonIfPersonParticipant(int invitationId, int participantId, CancellationToken cancellationToken) => await invitationValidator.CurrentUserIsValidSigningParticipantAsync(invitationId, participantId, cancellationToken); async Task <bool> BeAnExistingParticipant(int participantId, int invitationId, CancellationToken cancellationToken) => await invitationValidator.ParticipantExistsAsync(participantId, invitationId, cancellationToken); async Task <bool> BeUnsignedParticipant(int participantId, int invitationId, CancellationToken cancellationToken) => !await invitationValidator.ParticipantIsSignedAsync(participantId, invitationId, cancellationToken); bool HaveAValidRowVersion(string rowVersion) => rowVersionValidator.IsValid(rowVersion); }
public UpdateAttendedStatusOnParticipantCommandValidator(IInvitationValidator invitationValidator, IRowVersionValidator rowVersionValidator) { CascadeMode = CascadeMode.Stop; RuleFor(command => command) .MustAsync((command, cancellationToken) => BeAnExistingInvitation(command.InvitationId, cancellationToken)) .WithMessage(command => $"Invitation with this ID does not exist! Id={command.InvitationId}") .MustAsync((command, cancellationToken) => NotBeCancelledInvitation(command.InvitationId, cancellationToken)) .WithMessage(command => $"Cannot perform updates on cancelled invitation! Id={command.InvitationId}") .MustAsync((command, cancellationToken) => BeAnExistingParticipant(command.ParticipantId, command.InvitationId, cancellationToken)) .WithMessage(command => $"Participant with ID does not exist on invitation! ParticipantId={command.ParticipantId}") .Must(command => HaveAValidRowVersion(command.RowVersion)) .WithMessage(command => $"Participant doesn't have valid rowVersion! ParticipantRowVersion={command.RowVersion}") .MustAsync((command, cancellationToken) => HavePermissionToEdit(command.ParticipantId, command.InvitationId, cancellationToken)) .WithMessage("The current user does not have sufficient privileges to edit this participant.") .MustAsync((command, cancellationToken) => HaveOppositeAttendedStatusIfTouched(command.ParticipantId, command.InvitationId, command.Attended, cancellationToken)) .WithMessage("Cannot update participant to its current attendedStatus."); async Task <bool> BeAnExistingInvitation(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoExistsAsync(invitationId, cancellationToken); async Task <bool> NotBeCancelledInvitation(int invitationId, CancellationToken cancellationToken) => !await invitationValidator.IpoIsInStageAsync(invitationId, IpoStatus.Canceled, cancellationToken); async Task <bool> BeAnExistingParticipant(int participantId, int invitationId, CancellationToken cancellationToken) => await invitationValidator.ParticipantExistsAsync(participantId, invitationId, cancellationToken); async Task <bool> HavePermissionToEdit(int participantId, int invitationId, CancellationToken cancellationToken) => await invitationValidator.HasPermissionToEditParticipantAsync(participantId, invitationId, cancellationToken); async Task <bool> HaveOppositeAttendedStatusIfTouched(int participantId, int invitationId, bool attended, CancellationToken cancellationToken) => await invitationValidator.HasOppositeAttendedStatusIfTouchedAsync(participantId, invitationId, attended, cancellationToken); bool HaveAValidRowVersion(string rowVersion) => rowVersionValidator.IsValid(rowVersion); }
public AcceptPunchOutCommandValidator(IInvitationValidator invitationValidator, IRowVersionValidator rowVersionValidator) { CascadeMode = CascadeMode.Stop; RuleFor(command => command) .MustAsync((command, cancellationToken) => BeAnExistingInvitation(command.InvitationId, cancellationToken)) .WithMessage(command => $"Invitation with this ID does not exist! Id={command.InvitationId}") .MustAsync((command, cancellationToken) => BeAnInvitationInCompletedStage(command.InvitationId, cancellationToken)) .WithMessage(command => "Invitation is not in completed stage, and thus cannot be accepted!") .Must(command => HaveAValidRowVersion(command.InvitationRowVersion)) .WithMessage(command => $"Invitation row version is not valid! InvitationRowVersion={command.InvitationRowVersion}") .Must(command => HaveAValidRowVersion(command.ParticipantRowVersion)) .WithMessage(command => $"Participant row version is not valid! ParticipantRowVersion={command.ParticipantRowVersion}") .MustAsync((command, cancellationToken) => BeAnAccepterOnIpo(command.InvitationId, cancellationToken)) .WithMessage(command => "The IPO does not have a construction company assigned to accept the IPO!") .MustAsync((command, cancellationToken) => BeTheAssignedPersonIfPersonParticipant(command.InvitationId, cancellationToken)) .WithMessage(command => "Person signing is not the construction company assigned to accept this IPO, or there is not a valid construction company on the IPO!"); RuleForEach(command => command.Participants) .MustAsync((command, participant, _, cancellationToken) => BeAnExistingParticipant(participant.Id, command.InvitationId, cancellationToken)) .WithMessage((command, participant) => $"Participant with ID does not exist on invitation! Participant={participant.Id}") .Must((command, participant) => HaveAValidRowVersion(participant.RowVersion)) .WithMessage((command, participant) => $"Participant doesn't have valid rowVersion! Participant={participant.Id}"); async Task <bool> BeAnExistingInvitation(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoExistsAsync(invitationId, cancellationToken); async Task <bool> BeAnInvitationInCompletedStage(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoIsInStageAsync(invitationId, IpoStatus.Completed, cancellationToken); async Task <bool> BeAnAccepterOnIpo(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoHasAccepterAsync(invitationId, cancellationToken); async Task <bool> BeTheAssignedPersonIfPersonParticipant(int invitationId, CancellationToken cancellationToken) => await invitationValidator.CurrentUserIsValidAccepterParticipantAsync(invitationId, cancellationToken); async Task <bool> BeAnExistingParticipant(int participantId, int invitationId, CancellationToken cancellationToken) => await invitationValidator.ParticipantExistsAsync(participantId, invitationId, cancellationToken); bool HaveAValidRowVersion(string rowVersion) => rowVersionValidator.IsValid(rowVersion); }
public UpdateAttendedStatusAndNotesOnParticipantsCommandValidator(IInvitationValidator invitationValidator, IRowVersionValidator rowVersionValidator) { CascadeMode = CascadeMode.Stop; RuleFor(command => command) .MustAsync((command, cancellationToken) => BeAnExistingInvitation(command.InvitationId, cancellationToken)) .WithMessage(command => $"Invitation with this ID does not exist! Id={command.InvitationId}") .MustAsync((command, cancellationToken) => BeAnInvitationInCompletedStage(command.InvitationId, cancellationToken)) .WithMessage(command => "Invitation is not in completed stage, and thus cannot change attended statuses or notes!") .MustAsync((command, cancellationToken) => BeAContractorOnIpo(command.InvitationId, cancellationToken)) .WithMessage(command => "The IPO does not have a contractor assigned to the IPO!") .MustAsync((command, cancellationToken) => BeTheAssignedContractorIfPersonParticipant(command.InvitationId, cancellationToken)) .WithMessage(command => "User is not the contractor assigned to complete this IPO, or there is not a valid contractor on the IPO!"); RuleForEach(command => command.Participants) .MustAsync((command, participant, _, cancellationToken) => BeAnExistingParticipant(participant.Id, command.InvitationId, cancellationToken)) .WithMessage((command, participant) => $"Participant with ID does not exist on invitation! ParticipantId={participant.Id}") .Must((command, participant) => HaveAValidRowVersion(participant.RowVersion)) .WithMessage((command, participant) => $"Participant doesn't have valid rowVersion! ParticipantRowVersion={participant.RowVersion}"); async Task <bool> BeAnExistingInvitation(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoExistsAsync(invitationId, cancellationToken); async Task <bool> BeAnInvitationInCompletedStage(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoIsInStageAsync(invitationId, IpoStatus.Completed, cancellationToken); async Task <bool> BeAnExistingParticipant(int participantId, int invitationId, CancellationToken cancellationToken) => await invitationValidator.ParticipantExistsAsync(participantId, invitationId, cancellationToken); async Task <bool> BeTheAssignedContractorIfPersonParticipant(int invitationId, CancellationToken cancellationToken) => await invitationValidator.CurrentUserIsValidCompleterParticipantAsync(invitationId, cancellationToken); async Task <bool> BeAContractorOnIpo(int invitationId, CancellationToken cancellationToken) => await invitationValidator.IpoHasCompleterAsync(invitationId, cancellationToken); bool HaveAValidRowVersion(string rowVersion) => rowVersionValidator.IsValid(rowVersion); }
public UpdateTagStepAndRequirementsCommandValidator( IProjectValidator projectValidator, ITagValidator tagValidator, IStepValidator stepValidator, IRequirementDefinitionValidator requirementDefinitionValidator, IRowVersionValidator rowVersionValidator) { CascadeMode = CascadeMode.Stop; WhenAsync((command, token) => IsASupplierStepAsync(command.StepId, token), () => { WhenAsync((command, token) => NotBeAPoAreaTagAsync(command.TagId, token), () => { RuleFor(command => command) .MustAsync((_, command, token) => RequirementUsageIsForAllJourneysAsync( command.TagId, command.UpdatedRequirements.Where(u => !u.IsVoided).Select(u => u.TagRequirementId).ToList(), command.UpdatedRequirements.Where(u => u.IsVoided).Select(u => u.TagRequirementId).ToList(), command.NewRequirements.Select(r => r.RequirementDefinitionId).ToList(), token)) .WithMessage(_ => "Requirements must include requirements to be used both for supplier and other than suppliers!"); }).Otherwise(() => { RuleFor(command => command) .MustAsync((_, command, token) => RequirementUsageIsForSupplierAsync( command.TagId, command.UpdatedRequirements.Where(u => !u.IsVoided).Select(u => u.TagRequirementId).ToList(), command.UpdatedRequirements.Where(u => u.IsVoided).Select(u => u.TagRequirementId).ToList(), command.NewRequirements.Select(r => r.RequirementDefinitionId).ToList(), token)) .WithMessage(_ => "Requirements must include requirements to be used for supplier!") .MustAsync((command, token) => RequirementUsageIsNotForOtherThanSupplierAsync( command.TagId, command.UpdatedRequirements.Where(u => !u.IsVoided).Select(u => u.TagRequirementId).ToList(), command.UpdatedRequirements.Where(u => u.IsVoided).Select(u => u.TagRequirementId).ToList(), command.NewRequirements.Select(r => r.RequirementDefinitionId).ToList(), token)) .WithMessage(_ => "Requirements can not include requirements for other than suppliers!"); }); }).Otherwise(() => { RuleFor(command => command) .MustAsync((command, token) => NotBeAPoAreaTagAsync(command.TagId, token)) .WithMessage(_ => $"Step for a {TagType.PoArea.GetTagNoPrefix()} tag needs to be for supplier!") .MustAsync((_, command, token) => RequirementUsageIsForJourneysWithoutSupplierAsync( command.TagId, command.UpdatedRequirements.Where(u => !u.IsVoided).Select(u => u.TagRequirementId).ToList(), command.UpdatedRequirements.Where(u => u.IsVoided).Select(u => u.TagRequirementId).ToList(), command.NewRequirements.Select(r => r.RequirementDefinitionId).ToList(), token)) .WithMessage(_ => "Requirements must include requirements to be used for other than suppliers!"); }); WhenAsync((command, token) => IsAnAreaTagAsync(command.TagId, token), () => { RuleFor(command => command) .Must(command => !string.IsNullOrEmpty(command.Description)) .WithMessage(_ => "Description can not be blank!"); }).Otherwise(() => { RuleFor(command => command) .MustAsync((command, token) => NotChangeDescriptionAsync(command.TagId, command.Description, token)) .WithMessage(_ => "Tag must be an area tag to update description!"); }); RuleFor(command => command) .MustAsync((_, command, token) => RequirementsMustBeUniqueAfterUpdateAsync( command.TagId, command.NewRequirements.Select(r => r.RequirementDefinitionId).ToList(), token)) .WithMessage(_ => "Requirements must be unique!") .MustAsync((command, token) => NotBeAClosedProjectForTagAsync(command.TagId, token)) .WithMessage(command => $"Project for tag is closed! Tag={command.TagId}") .MustAsync((command, token) => BeAnExistingTagAsync(command.TagId, token)) .WithMessage(command => $"Tag doesn't exist! Tag={command.TagId}") .MustAsync((command, token) => NotBeAVoidedTagAsync(command.TagId, token)) .WithMessage(command => $"Tag is voided! Tag={command.TagId}") .MustAsync((command, token) => NotChangedToAVoidedStepAsync(command.TagId, command.StepId, token)) .WithMessage(command => $"Step is voided! Step={command.StepId}") .Must(command => HaveAValidRowVersion(command.RowVersion)) .WithMessage(command => $"Not a valid row version! Row version={command.RowVersion}"); RuleForEach(command => command.UpdatedRequirements) .MustAsync((command, req, _, token) => BeAnExistingTagRequirementAsync(command.TagId, req.TagRequirementId, token)) .WithMessage((_, req) => $"Requirement doesn't exist! Requirement={req.TagRequirementId}"); RuleForEach(command => command.DeletedRequirements) .MustAsync((command, req, _, token) => BeAnExistingTagRequirementAsync(command.TagId, req.TagRequirementId, token)) .WithMessage((_, req) => $"Requirement doesn't exist! Requirement={req.TagRequirementId}") .MustAsync((command, req, _, token) => BeAVoidedTagRequirementAsync( command.TagId, req.TagRequirementId, command.UpdatedRequirements.Where(u => u.IsVoided).Select(u => u.TagRequirementId).ToList(), token)) .WithMessage((_, req) => $"Requirement is not voided! Requirement={req.TagRequirementId}"); RuleForEach(command => command.NewRequirements) .MustAsync((_, req, _, token) => BeAnExistingRequirementDefinitionAsync(req.RequirementDefinitionId, token)) .WithMessage((_, req) => $"Requirement definition doesn't exist! Requirement definition={req.RequirementDefinitionId}") .MustAsync((_, req, _, token) => NotBeAVoidedRequirementDefinitionAsync(req.RequirementDefinitionId, token)) .WithMessage((_, req) => $"Requirement definition is voided! Requirement definition={req.RequirementDefinitionId}"); async Task <bool> RequirementsMustBeUniqueAfterUpdateAsync( int tagId, List <int> requirementDefinitionIdsToBeAdded, CancellationToken token) => requirementDefinitionIdsToBeAdded.Count == 0 || await tagValidator.AllRequirementsWillBeUniqueAsync(tagId, requirementDefinitionIdsToBeAdded, token); async Task <bool> RequirementUsageIsNotForOtherThanSupplierAsync( int tagId, List <int> tagRequirementIdsToBeUnvoided, List <int> tagRequirementIdsToBeVoided, List <int> requirementDefinitionIdsToBeAdded, CancellationToken token) => !await tagValidator.RequirementHasAnyForOtherThanSuppliersUsageAsync( tagId, tagRequirementIdsToBeUnvoided, tagRequirementIdsToBeVoided, requirementDefinitionIdsToBeAdded, token); async Task <bool> RequirementUsageIsForSupplierAsync( int tagId, List <int> tagRequirementIdsToBeUnvoided, List <int> tagRequirementIdsToBeVoided, List <int> requirementDefinitionIdsToBeAdded, CancellationToken token) => await tagValidator.RequirementUsageWillCoverForSuppliersAsync( tagId, tagRequirementIdsToBeUnvoided, tagRequirementIdsToBeVoided, requirementDefinitionIdsToBeAdded, token); async Task <bool> RequirementUsageIsForAllJourneysAsync( int tagId, List <int> tagRequirementIdsToBeUnvoided, List <int> tagRequirementIdsToBeVoided, List <int> requirementDefinitionIdsToBeAdded, CancellationToken token) => await tagValidator.RequirementUsageWillCoverBothForSupplierAndOtherAsync( tagId, tagRequirementIdsToBeUnvoided, tagRequirementIdsToBeVoided, requirementDefinitionIdsToBeAdded, token); async Task <bool> RequirementUsageIsForJourneysWithoutSupplierAsync( int tagId, List <int> tagRequirementIdsToBeUnvoided, List <int> tagRequirementIdsToBeVoided, List <int> requirementDefinitionIdsToBeAdded, CancellationToken token) => await tagValidator.RequirementUsageWillCoverForOtherThanSuppliersAsync( tagId, tagRequirementIdsToBeUnvoided, tagRequirementIdsToBeVoided, requirementDefinitionIdsToBeAdded, token); async Task <bool> IsASupplierStepAsync(int stepId, CancellationToken token) => await stepValidator.IsForSupplierAsync(stepId, token); async Task <bool> NotBeAClosedProjectForTagAsync(int tagId, CancellationToken token) => !await projectValidator.IsClosedForTagAsync(tagId, token); async Task <bool> IsAnAreaTagAsync(int tagId, CancellationToken token) => await tagValidator.VerifyTagIsAreaTagAsync(tagId, token); async Task <bool> BeAnExistingTagAsync(int tagId, CancellationToken token) => await tagValidator.ExistsAsync(tagId, token); async Task <bool> NotBeAVoidedTagAsync(int tagId, CancellationToken token) => !await tagValidator.IsVoidedAsync(tagId, token); async Task <bool> NotBeAPoAreaTagAsync(int tagId, CancellationToken token) => !await tagValidator.VerifyTagTypeAsync(tagId, TagType.PoArea, token); async Task <bool> NotChangedToAVoidedStepAsync(int tagId, int stepId, CancellationToken token) => await tagValidator.HasStepAsync(tagId, stepId, token) || !await stepValidator.IsVoidedAsync(stepId, token); async Task <bool> BeAnExistingRequirementDefinitionAsync(int requirementDefinitionId, CancellationToken token) => await requirementDefinitionValidator.ExistsAsync(requirementDefinitionId, token); async Task <bool> NotBeAVoidedRequirementDefinitionAsync(int requirementDefinitionId, CancellationToken token) => !await requirementDefinitionValidator.IsVoidedAsync(requirementDefinitionId, token); async Task <bool> BeAnExistingTagRequirementAsync(int tagId, int tagRequirementId, CancellationToken token) => await tagValidator.HasRequirementAsync(tagId, tagRequirementId, token); async Task <bool> BeAVoidedTagRequirementAsync( int tagId, int tagRequirementId, List <int> tagRequirementIdsToBeVoided, CancellationToken token) { if (tagRequirementIdsToBeVoided.Contains(tagRequirementId)) { return(true); } return(await tagValidator.IsRequirementVoidedAsync(tagId, tagRequirementId, token)); } bool HaveAValidRowVersion(string rowVersion) => rowVersionValidator.IsValid(rowVersion); async Task <bool> NotChangeDescriptionAsync(int tagId, string description, CancellationToken token) => description == null || await tagValidator.VerifyTagDescriptionAsync(tagId, description, token); }