Exemple #1
0
        public async Task AndCheckingAllowedVersusAttemtpedMinWage(WageUnit wageUnit, decimal allowedMinimumHourlyWage, decimal attemptedFixedWage, bool expectedIsValid)
        {
            var request = new CreateApprenticeshipRequest
            {
                WageType          = WageType.CustomWageFixed,
                WageUnit          = wageUnit,
                FixedWage         = attemptedFixedWage,
                HoursPerWeek      = 36,
                ExpectedStartDate = _fixture.CreateFutureDateTime()
            };
            var context = GetValidationContextForProperty(request, req => req.FixedWage);

            _fixture      = new Fixture().Customize(new AutoMoqCustomization());
            _mockSelector = _fixture.Freeze <Mock <IGetMinimumWagesService> >();
            _mockSelector
            .Setup(selector => selector.GetApprenticeMinimumWageRate(It.IsAny <DateTime>()))
            .Returns(allowedMinimumHourlyWage);

            _fixture.Inject <IHourlyWageCalculator>(new HourlyWageCalculator());

            _validator = _fixture.Create <CreateApprenticeshipRequestValidator>();

            var result = await _validator.ValidateAsync(context).ConfigureAwait(false);

            result.IsValid.Should().Be(expectedIsValid);
            if (!result.IsValid)
            {
                result.Errors.First().ErrorCode
                .Should().Be(ErrorCodes.CreateApprenticeship.FixedWage);
                result.Errors.First().ErrorMessage
                .Should().Be(ErrorMessages.CreateApprenticeship.FixedWageIsBelowApprenticeMinimumWage);
            }
        }
Exemple #2
0
        public decimal Calculate(decimal wageValue, WageUnit wageUnit, decimal hoursPerWeek)
        {
            if (hoursPerWeek <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(hoursPerWeek), hoursPerWeek, HoursPerWeekZeroErrorMessage);
            }

            decimal calculatedHourlyWage;

            switch (wageUnit)
            {
            case WageUnit.Weekly:
                calculatedHourlyWage = WageCalculator.GetHourRate(wageValue, SFA.DAS.VacancyServices.Wage.WageUnit.Weekly, hoursPerWeek);
                break;

            case WageUnit.Monthly:
                calculatedHourlyWage = WageCalculator.GetHourRate(wageValue, SFA.DAS.VacancyServices.Wage.WageUnit.Monthly, hoursPerWeek);
                break;

            case WageUnit.Annually:
                calculatedHourlyWage = WageCalculator.GetHourRate(wageValue, SFA.DAS.VacancyServices.Wage.WageUnit.Annually, hoursPerWeek);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(wageUnit), wageUnit, IncorrectWageTypeErrorMessage);
            }

            return(calculatedHourlyWage);
        }
Exemple #3
0
        private static WageUnit CorrectWageUnit(WageType type, WageUnit unit)
        {
            switch (type)
            {
            case WageType.CustomRange:
                if (unit == WageUnit.NotApplicable)
                {
                    return(WageUnit.Weekly);
                }
                return(unit);

            case WageType.LegacyText:
            case WageType.CompetitiveSalary:
            case WageType.ToBeAgreedUponAppointment:
            case WageType.Unwaged:
                return(WageUnit.NotApplicable);

            case WageType.Custom:
                switch (unit)
                {
                case WageUnit.Weekly:
                case WageUnit.Monthly:
                case WageUnit.Annually:
                case WageUnit.NotApplicable:
                    return(unit);

                default:
                    throw new ArgumentOutOfRangeException(nameof(Unit), $"Invalid Wage Unit: {unit}");
                }

            case WageType.LegacyWeekly:
            default:
                return(WageUnit.Weekly);
            }
        }
        public void ShouldGetTheCorrectWageUnitForCustomWages(WageUnit wageUnit, WageUnit expected)
        {
            var wage = new Wage(WageType.Custom, null, null, null, string.Empty, wageUnit, null, null);

            var actual = wage.Unit;

            actual.Should().Be(expected);
        }
        public void ShouldGetDisplayAmountWithFrequencyPostfix(WageUnit wageUnit, decimal displayAmount, string expected)
        {
            // Act.
            var actual = WagePresenter.GetDisplayAmountWithFrequencyPostfix(WageType.Custom, displayAmount, null, null, null, wageUnit, null, null);

            // Assert.
            actual.Should().Be(expected);
        }
        public void RunTestCases(WageUnit wageUnit, decimal minWage, double hoursPerWeek, decimal expectedResult)
        {
            var minimumWageCalculator = new HourlyWageCalculator();

            var result = minimumWageCalculator.Calculate(minWage, wageUnit, (decimal)hoursPerWeek);

            result.Should().BeApproximately(expectedResult, 0.01m);
        }
        public void ShouldGetHeaderDisplayTextForWageUnit(WageUnit wageUnit, string expected)
        {
            // Act.
            var actual = wageUnit.GetHeaderDisplayText();

            // Assert.
            actual.Should().Be(expected);
        }
        public void ShouldSetCorrectWageUnit(WageType type, WageUnit suppliedUnit, WageUnit expectedUnit)
        {
            //Arrange
            //Act
            var result = new Wage(type, null, null, null, null, suppliedUnit, null, null);

            //Assert
            result.Unit.Should().Be(expectedUnit);
        }
        public void ShouldGetTheCorrectWageUnitForNonCustomWages(WageType wageType, WageUnit expected)
        {
            var wage = new Wage(wageType, null, null, null, string.Empty, WageUnit.NotApplicable, null, null);
            // Act.
            var actual = wage.Unit;

            // Assert.
            actual.Should().Be(expected);
        }
        public void ShouldGetDisplayAmountWithFrequencyPostfix(WageUnit wageUnit, decimal displayAmount, string expected)
        {
            // Act.
            string actual =
                WagePresenter.GetDisplayTextFrequencyPostfix(WageType.Custom, wageUnit,
                                                             new WageDetails()
            {
                Amount = displayAmount
            });

            // Assert.
            actual.Should().Be(expected);
        }
Exemple #11
0
        public static string GetDisplayTextFrequencyPostfix(WageType type, WageUnit unit, WageDetails wageDetails)
        {
            string postfix = unit.GetWagePostfix();

            string displayAmount = GetDisplayText(type, unit, wageDetails);

            if (string.IsNullOrWhiteSpace(displayAmount))
            {
                return(postfix);
            }

            return($"{displayAmount} {postfix}");
        }
        public void ShouldGetDisplayAmountWithFrequencyPostfixNationalMinimums(WageUnit wageUnit, string expected)
        {
            // Act.
            string actual = WagePresenter.GetDisplayTextFrequencyPostfix(WageType.ApprenticeshipMinimum, wageUnit,
                                                                         new WageDetails()
            {
                HoursPerWeek = 37.5m,
                StartDate    = new DateTime(2016, 10, 30)
            });

            // Assert.
            actual.Should().Be(expected);
        }
Exemple #13
0
        public void ShouldShowCustomWageAmount(decimal wage, WageUnit wageUnit, string expectedDisplayText)
        {
            var details = new WorkingWeekAndWage();

            var viewModel = new VacancyViewModel()
            {
                ProviderSite = new ProviderSiteViewModel()
                {
                    Address = new AddressViewModel()
                },
                FurtherVacancyDetailsViewModel = new FurtherVacancyDetailsViewModel
                {
                    VacancyDatesViewModel = new VacancyDatesViewModel
                    {
                        ClosingDate       = new DateViewModel(DateTime.Now),
                        PossibleStartDate = new DateViewModel(DateTime.Now)
                    },
                    Wage = new WageViewModel()
                    {
                        Amount = wage, Unit = wageUnit
                    }
                },
                NewVacancyViewModel = new NewVacancyViewModel
                {
                    VacancyOwnerRelationship = new VacancyOwnerRelationshipViewModel()
                    {
                        Employer = new EmployerViewModel()
                        {
                            Address = new AddressViewModel()
                        }
                    },
                    LocationAddresses = new List <VacancyLocationAddressViewModel>(),
                    OfflineVacancy    = false
                },
                TrainingDetailsViewModel              = new TrainingDetailsViewModel(),
                VacancyQuestionsViewModel             = new VacancyQuestionsViewModel(),
                VacancyRequirementsProspectsViewModel = new VacancyRequirementsProspectsViewModel(),
                Status      = VacancyStatus.Draft,
                VacancyType = VacancyType.Apprenticeship
            };

            var view = details.RenderAsHtml(_context, viewModel);

            view.GetElementbyId("vacancy-wage").InnerHtml.Should().Be(expectedDisplayText);
        }
Exemple #14
0
        public static decimal GetHourRate(decimal wage, WageUnit wageUnit, decimal hoursPerWeek)
        {
            switch (wageUnit)
            {
            case WageUnit.Weekly:
                return(wage / hoursPerWeek);

            case WageUnit.Annually:
                return(wage / WageConstants.WeeksPerYear / hoursPerWeek);

            case WageUnit.Monthly:
                return(wage / WageConstants.WeeksPerYear * WageConstants.MonthPerYear / hoursPerWeek);

            case WageUnit.NotApplicable:
                return(0);

            default:
                throw new ArgumentOutOfRangeException(nameof(wageUnit), wageUnit, null);
            }
        }
Exemple #15
0
        private static string GetWagePostfix(this WageUnit wageUnit)
        {
            switch (wageUnit)
            {
            case WageUnit.Annually:
                return(WageConstants.PerYearText);

            case WageUnit.Monthly:
                return(WageConstants.PerMonthText);

            case WageUnit.Weekly:
                return(WageConstants.PerWeekText);

            case WageUnit.NotApplicable:
                return(string.Empty);

            default:
                throw new ArgumentOutOfRangeException(nameof(wageUnit), $"Invalid Wage Unit: {wageUnit}");
            }
        }
Exemple #16
0
        public static string GetHeaderDisplayText(this WageUnit wageUnit)
        {
            switch (wageUnit)
            {
            case WageUnit.Annually:
                return(AnnualWageText);

            case WageUnit.Monthly:
                return(MonthlyWageText);

            case WageUnit.Weekly:
                return(WeeklyWageText);

            case WageUnit.NotApplicable:
                return(WageText);

            default:
                throw new ArgumentOutOfRangeException(nameof(wageUnit), $"Invalid Wage Unit: {wageUnit}");
            }
        }
        [TestCase(2652, WageUnit.Annually, 15, true)]    //3.40 pounds per hour
        public void ApprenticeMinimumWage_PerHour_AfterOctFirst2016(decimal wage, WageUnit wageUnit, decimal hoursPerWeek, bool expectValid)
        {
            //After 1st of october 2016 the National Minimum Wage for Apprentices increases to £3.40/hour
            var viewModel = new FurtherVacancyDetailsViewModel
            {
                Wage = new WageViewModel()
                {
                    Classification = WageClassification.Custom, CustomType = CustomWageType.Fixed, Amount = wage, Unit = wageUnit, HoursPerWeek = hoursPerWeek
                },
                VacancyDatesViewModel = new VacancyDatesViewModel
                {
                    PossibleStartDate = new DateViewModel(new DateTime(2016, 10, 1))
                }
            };
            var vacancyViewModel = new VacancyViewModelBuilder().With(viewModel).Build();

            var response = _validator.Validate(viewModel, ruleSet: RuleSet);

            _aggregateValidator.Validate(vacancyViewModel);
            var aggregateResponse = _aggregateValidator.Validate(vacancyViewModel, ruleSet: RuleSet);

            if (expectValid)
            {
                _validator.ShouldNotHaveValidationErrorFor(vm => vm.Wage, vm => vm.Wage.Amount, viewModel, RuleSet);
                _aggregateValidator.ShouldNotHaveValidationErrorFor(vm => vm.FurtherVacancyDetailsViewModel, vm => vm.FurtherVacancyDetailsViewModel.Wage, vm => vm.FurtherVacancyDetailsViewModel.Wage.Amount, vacancyViewModel);
                _aggregateValidator.ShouldNotHaveValidationErrorFor(vm => vm.FurtherVacancyDetailsViewModel, vm => vm.FurtherVacancyDetailsViewModel.Wage, vm => vm.FurtherVacancyDetailsViewModel.Wage.Amount, vacancyViewModel, RuleSet);
            }
            else
            {
                _validator.ShouldHaveValidationErrorFor(vm => vm.Wage, vm => vm.Wage.Amount, viewModel, RuleSet);
                _aggregateValidator.ShouldHaveValidationErrorFor(vm => vm.FurtherVacancyDetailsViewModel, vm => vm.FurtherVacancyDetailsViewModel.Wage, vm => vm.FurtherVacancyDetailsViewModel.Wage.Amount, vacancyViewModel);
                _aggregateValidator.ShouldHaveValidationErrorFor(vm => vm.FurtherVacancyDetailsViewModel, vm => vm.FurtherVacancyDetailsViewModel.Wage, vm => vm.FurtherVacancyDetailsViewModel.Wage.Amount, vacancyViewModel, RuleSet);

                var error = response.Errors.SingleOrDefault(e => e.PropertyName == "Wage.Amount");
                error.Should().NotBeNull();
                error?.ErrorMessage.Should().Be("The wage should not be less then the new National Minimum Wage for apprentices effective from 1 Oct 2016");
                var aggregateError = aggregateResponse.Errors.SingleOrDefault(e => e.PropertyName == "FurtherVacancyDetailsViewModel.Wage.Amount");
                aggregateError.Should().NotBeNull();
                aggregateError?.ErrorMessage.Should().Be("The wage should not be less then the new National Minimum Wage for apprentices effective from 1 Oct 2016");
            }
        }
        public async Task AndCallingValidate(WageUnit wageUnitToValidate, bool expectedIsValid,
                                             string expectedErrorCodes, string expectedErrorMessages)
        {
            var fixture = new Fixture().Customize(new AutoMoqCustomization());
            var request = new CreateApprenticeshipRequest
            {
                WageUnit = wageUnitToValidate
            };

            var context = GetValidationContextForProperty(request, req => req.WageUnit);

            var validator = fixture.Create <CreateApprenticeshipRequestValidator>();

            var result = await validator.ValidateAsync(context);

            result.IsValid.Should().Be(expectedIsValid);
            if (!expectedIsValid)
            {
                result.Errors.First().ErrorCode
                .Should().Be(expectedErrorCodes);
                result.Errors.First().ErrorMessage
                .Should().Be(expectedErrorMessages);
            }
        }
Exemple #19
0
 public static decimal GetHourRateRoundAsMoney(decimal wage, WageUnit wageUnit, decimal hoursPerWeek)
 {
     return(RoundAsMoney(GetHourRate(wage, wageUnit, hoursPerWeek)));
 }
Exemple #20
0
 public Wage(WageType type, decimal?amount, decimal?amountLowerBound, decimal?amountUpperBound, string text, WageUnit unit, decimal?hoursPerWeek, string reasonForType)
 {
     Type             = type;
     Amount           = amount;
     AmountLowerBound = amountLowerBound;
     AmountUpperBound = amountUpperBound;
     ReasonForType    = reasonForType;
     Text             = text;
     HoursPerWeek     = hoursPerWeek;
     Unit             = CorrectWageUnit(type, unit);
 }
Exemple #21
0
        public static string GetDisplayText(WageType type, WageUnit unit, WageDetails details)
        {
            WageDetails wageDetails = details ?? new WageDetails();

            switch (type)
            {
            case WageType.Custom:
                return(FormatWageAmount(wageDetails.Amount));

            case WageType.ApprenticeshipMinimum:

                if (!wageDetails.HoursPerWeek.HasValue || wageDetails.HoursPerWeek.Value == 0)
                {
                    return($"£{WageConstants.UnknownText}");
                }

                if (unit == WageUnit.Annually)
                {
                    return(GetYearlyApprenticeshipMinimumWage(wageDetails.HoursPerWeek.Value, wageDetails.StartDate));
                }

                return(GetWeeklyApprenticeshipMinimumWage(wageDetails.HoursPerWeek.Value, wageDetails.StartDate));

            case WageType.NationalMinimum:
                if (!wageDetails.HoursPerWeek.HasValue || wageDetails.HoursPerWeek.Value == 0)
                {
                    return($"£{WageConstants.UnknownText}");
                }

                if (unit == WageUnit.Annually)
                {
                    return(GetYearlyNationalMinimumWage(wageDetails.HoursPerWeek.Value, wageDetails.StartDate));
                }

                return(GetWeeklyNationalMinimumWage(wageDetails.HoursPerWeek.Value, wageDetails.StartDate));

            case WageType.Text:

                //if it's unknown, return standard unknown text
                string displayText = wageDetails.Text ?? $"£{WageConstants.UnknownText}";

                //if it's not unknown, then prepend a '£' sign to its decimal value.
                decimal wageDecimal;

                //if it's already got a '£' sign, or is text, fail to parse and all is good => return value.
                if (decimal.TryParse(displayText, out wageDecimal))
                {
                    displayText = FormatWageAmount(wageDecimal);
                }

                return(displayText);

            case WageType.CustomRange:
                return
                    ($"{FormatWageAmount(wageDetails.LowerBound)} - {FormatWageAmount(wageDetails.UpperBound)}");

            case WageType.CompetitiveSalary:
                return(WageConstants.CompetitiveSalaryText);

            case WageType.ToBeAgreedUponAppointment:
                return(WageConstants.ToBeAGreedUponAppointmentText);

            case WageType.Unwaged:
                return(WageConstants.UnwagedText);

            default:
                throw new ArgumentOutOfRangeException(nameof(type), type,
                                                      $"Invalid Wage Type: {type}");
            }
        }
Exemple #22
0
        public static string GetDisplayAmountWithFrequencyPostfix(WageType type, decimal?amount, decimal?amountLowerBound, decimal?amountUpperBound, string text, WageUnit unit, decimal?hoursPerWeek, DateTime?possibleDateTime)
        {
            var postfix = unit.GetWagePostfix();

            var displayAmount = GetDisplayAmount(type, amount, amountLowerBound, amountUpperBound, text, hoursPerWeek, possibleDateTime);

            if (string.IsNullOrWhiteSpace(displayAmount))
            {
                return(postfix);
            }

            return($"{displayAmount} {postfix}");
        }