public void CreateJobValidator_GivenNullJobDefinition_ValidIsFalse()
        {
            //Arrange
            CreateJobValidationModel createJobValidationModel = CreateNewCreateJobValidationModel();

            createJobValidationModel.JobDefinition = null;

            CreateJobValidator validator = new CreateJobValidator();

            //Act
            ValidationResult result = validator.Validate(createJobValidationModel);

            //Assert
            result
            .IsValid
            .Should()
            .BeFalse();

            result
            .Errors
            .Count
            .Should()
            .Be(1);

            result
            .Errors
            .First()
            .ErrorMessage
            .Should()
            .Be("Null job definition was provided");
        }
        public void CreateJobValidator_GivenDefinitionRequiresMessageBodyButNoMessageBodyProvided_ValidIsFalse()
        {
            //Arrange
            CreateJobValidationModel createJobValidationModel = CreateNewCreateJobValidationModel();

            createJobValidationModel.JobCreateModel.MessageBody = "";

            CreateJobValidator validator = new CreateJobValidator();

            //Act
            ValidationResult result = validator.Validate(createJobValidationModel);

            //Assert
            result
            .IsValid
            .Should()
            .BeFalse();

            result
            .Errors
            .Count
            .Should()
            .Be(1);

            result
            .Errors
            .First()
            .ErrorMessage
            .Should()
            .Be("A message body is required when using job definition: 'job-def-1'");
        }
        public void CreateJobValidator_GivenDefinitionButMissingSessionProperty_ValidIsFalse()
        {
            //Arrange
            CreateJobValidationModel createJobValidationModel = CreateNewCreateJobValidationModel();

            createJobValidationModel.JobDefinition.SessionMessageProperty = "prop-3";

            CreateJobValidator validator = new CreateJobValidator();

            //Act
            ValidationResult result = validator.Validate(createJobValidationModel);

            //Assert
            result
            .IsValid
            .Should()
            .BeFalse();

            result
            .Errors
            .Count
            .Should()
            .Be(1);

            result
            .Errors
            .First()
            .ErrorMessage
            .Should()
            .Be($"Session Message property 'prop-3' is required when using job definition: 'job-def-1'");
        }
        public void CreateJobValidator_GivenDefinitionRequiresMessagePropertiesButPropertiesSupplieddoNotMatch_ValidIsFalse()
        {
            //Arrange
            CreateJobValidationModel createJobValidationModel = CreateNewCreateJobValidationModel();

            createJobValidationModel.JobCreateModel.Properties = new Dictionary <string, string>
            {
                { "prop-1", "property 1" }
            };

            CreateJobValidator validator = new CreateJobValidator();

            //Act
            ValidationResult result = validator.Validate(createJobValidationModel);

            //Assert
            result
            .IsValid
            .Should()
            .BeFalse();

            result
            .Errors
            .Count
            .Should()
            .Be(1);

            result
            .Errors
            .First()
            .ErrorMessage
            .Should()
            .Be("Message property 'prop-2' is required when using job definition: 'job-def-1'");
        }
        public void CreateJobValidator_GivenDefinitionRequiresMessagePropertiesButNoneWereSet_ValidIsFalse()
        {
            //Arrange
            CreateJobValidationModel createJobValidationModel = CreateNewCreateJobValidationModel();

            createJobValidationModel.JobCreateModel.Properties = null;

            CreateJobValidator validator = new CreateJobValidator();

            //Act
            ValidationResult result = validator.Validate(createJobValidationModel);

            //Assert
            result
            .IsValid
            .Should()
            .BeFalse();

            result
            .Errors
            .Count
            .Should()
            .Be(1);

            result
            .Errors
            .First()
            .ErrorMessage
            .Should()
            .Be("Message properties are required when using job definition: 'job-def-1'");
        }
Beispiel #6
0
        public void ShouldHaveErrorWhenItemsIsEmpty()
        {
            var subject = new CreateJobRequest
            {
                Items = new List <IJobItem>()
            };
            var target = new CreateJobValidator();

            target.ShouldHaveValidationErrorFor(s => s.Items, subject);
        }
Beispiel #7
0
        public void ShouldHaveErrorWhenNumberOfTyresExceedsMaximum()
        {
            var subject = new CreateJobRequest
            {
                Items = Enumerable.Repeat(new TyreReplacement(), 10)
            };
            var target = new CreateJobValidator();

            target.ShouldHaveValidationErrorFor(s => s.Items, subject)
            .WithErrorMessage($"{CreateJobValidator.MaximumTyreReplacementCountExceeded}4");
        }
Beispiel #8
0
        public CreateJobResult CreateJob(CreateJobRequest request)
        {
            _logger.LogInformation("Validating CreateJobRequest...");
            var requestValidator = new CreateJobValidator();
            var validationResult = requestValidator.Validate(request);

            if (!validationResult.IsValid)
            {
                _logger.LogWarning("Validation failed", validationResult.Errors);
                return(CreateJobResult.Failed(validationResult.Errors.Select(e => e.ErrorMessage).ToArray()));
            }

            // Labour
            var labourInMinutes = CalculateTotalLabour(request.Items);

            if (labourInMinutes > request.ReferenceLabourInMinutes)
            {
                _logger.LogWarning($"CreateJob declined. Calculated labour of '{labourInMinutes}' exceeded given value of '{request.ReferenceLabourInMinutes}'");
                return(CreateJobResult.Declined("Calculated total labour exceeds given value"));
            }

            // Costs
            // TODO: This logic could use be put into dedicated validators - but that would move this business logic away
            var cost = CalculateTotalCost(request.Items);

            // TODO: Possible divide by zero exception here - add logic to decline if so?
            var difference = Math.Abs(request.ReferencePrice / cost - 1);

            if (difference >= CostReferralThresholdMin && Math.Abs(difference) < CostReferralThresholdMax)
            {
                // TODO: Do something here for referral...
                _logger.LogInformation($"CreateJob referred. Total job cost '{cost}' versus '{request.ReferencePrice}' (Difference: {difference * 100:N2}% between {CostReferralThresholdMin * 100:N2}% and {CostReferralThresholdMax * 100:N2}%)");
                return(CreateJobResult.Referred());
            }

            if (difference >= CostDeclineThreshold)
            {
                // TODO: Do something here for declining...
                _logger.LogWarning($"CreateJob declined. Total job cost '{cost}' versus '{request.ReferencePrice}' (Difference: {difference * 100:N2}% >= {CostDeclineThreshold * 100:N2}%)");
                return(CreateJobResult.Declined(DeclinedMessage));
            }

            if (difference <= CostApprovalThreshold)
            {
                // TODO: Do something here for approval...
                _logger.LogInformation($"CreateJob approved. Total job cost '{cost}' versus '{request.ReferencePrice}' (Difference: {difference * 100:N2}% <= {CostApprovalThreshold * 100:N2}%)");
                return(CreateJobResult.Approved());
            }
            else
            {
                // Not enough rules - are the thresholds on a sliding scale? If so, we can fix this with a collection of thresholds instead
                return(CreateJobResult.Declined(UnknownErrorMessage));
            }
        }
        public void CreateJobValidator_GivenValidModel_ValidIsTrue()
        {
            //Arrange
            CreateJobValidationModel createJobValidationModel = CreateNewCreateJobValidationModel();

            CreateJobValidator validator = new CreateJobValidator();

            //Act
            ValidationResult result = validator.Validate(createJobValidationModel);

            //Assert
            result
            .IsValid
            .Should()
            .BeTrue();
        }
Beispiel #10
0
        public void ShouldNotErrorWhenBrakeDiscAndPadsArePaired()
        {
            var subject = new CreateJobRequest
            {
                Items = new IJobItem[] {
                    new BrakeDiscReplacement {
                        Position = WheelPosition.NearsideFront
                    },
                    new BrakePadReplacement {
                        Position = WheelPosition.NearsideFront
                    },
                }
            };
            var target = new CreateJobValidator();

            target.ShouldNotHaveValidationErrorFor(s => s.Items, subject);
        }
Beispiel #11
0
        public void ShouldNotErrorWhenTyreHasPair()
        {
            var subject = new CreateJobRequest
            {
                Items = new IJobItem[] {
                    new TyreReplacement {
                        Position = WheelPosition.NearsideFront
                    },
                    new TyreReplacement {
                        Position = WheelPosition.OffsideFront
                    }
                }
            };
            var target = new CreateJobValidator();

            target.ShouldNotHaveValidationErrorFor(s => s.Items, subject);
        }
Beispiel #12
0
        public void ShouldHaveErrorWhenBrakeDiscAndPadsAreNotPaired()
        {
            var subject = new CreateJobRequest
            {
                Items = new IJobItem[] {
                    new BrakeDiscReplacement {
                        Position = WheelPosition.NearsideFront
                    },
                    new BrakePadReplacement {
                        Position = WheelPosition.OffsideFront
                    },
                }
            };
            var target = new CreateJobValidator();

            target.ShouldHaveValidationErrorFor(s => s.Items, subject)
            .WithErrorMessage($"{CreateJobValidator.BrakeDiscAndPadsMustBePaired}");
        }
Beispiel #13
0
        public void ShouldHaveErrorWhenTyreDoesNotHavePair()
        {
            var subject = new CreateJobRequest
            {
                Items = new IJobItem[] {
                    new TyreReplacement {
                        Position = WheelPosition.NearsideFront
                    },
                    new TyreReplacement {
                        Position = WheelPosition.NearsideFront
                    }
                }
            };
            var target = new CreateJobValidator();

            target.ShouldHaveValidationErrorFor(s => s.Items, subject)
            .WithErrorMessage($"{CreateJobValidator.TyreReplacementsMustBePaired}");
        }
        public void CreateJobValidator_GivenValidModelWithSessionConfigured_ValidIsTrue()
        {
            //Arrange
            CreateJobValidationModel createJobValidationModel = CreateNewCreateJobValidationModel();

            createJobValidationModel.JobDefinition.SessionMessageProperty = "prop-3";

            createJobValidationModel.JobCreateModel.Properties.Add("prop-3", "property 3");

            CreateJobValidator validator = new CreateJobValidator();

            //Act
            ValidationResult result = validator.Validate(createJobValidationModel);

            //Assert
            result
            .IsValid
            .Should()
            .BeTrue();
        }
Beispiel #15
0
 public EfCreateJobCommand(MovingContext context, CreateJobValidator validator)
 {
     _context   = context;
     _validator = validator;
 }