public void Should_fail_if_discounts_exceed() { var discounts = new List <decimal> { 5m }; decimal MarkupFunction(decimal amount) => amount * 1.04m; var result = DiscountsValidator.DiscountsDontExceedMarkups(discounts, MarkupFunction); Assert.True(result.IsFailure); }
public void Should_pass_if_discounts_dont_exceed() { var discounts = new List <decimal> { 2, 1 }; decimal MarkupFunction(decimal amount) => amount * 1.04m; var result = DiscountsValidator.DiscountsDontExceedMarkups(discounts, MarkupFunction); Assert.True(result.IsSuccess); }
public async Task <Result> ChangeActivityState(int agencyId, int discountId, bool newActivityState) { return(await Get(agencyId, discountId) .Check(DiscountDoesntExceedMarkups) .BindWithTransaction(_context, discount => Result.Success(discount) .Tap(Update) .Check(WriteAuditLog))); Task Update(Discount discount) => this.Update(discount, d => d.IsActive = newActivityState); Task <Result> WriteAuditLog(Discount _) => _managementAuditService.Write(ManagementEventType.DiscountEdit, new DiscountActivityStateEventData(agencyId, newActivityState)); async Task <Result <Discount> > DiscountDoesntExceedMarkups(Discount discount) { // We need additional check for activated discounts // They can exceed markups if (!newActivityState) { return(Result.Success(discount)); } var markupPolicy = await _context.MarkupPolicies.SingleOrDefaultAsync(x => x.Id == discount.TargetPolicyId); var markupFunction = _templateService.CreateFunction(markupPolicy.TemplateId, markupPolicy.TemplateSettings); var allDiscounts = await _context.Discounts .Where(x => x.TargetPolicyId == markupPolicy.Id) .Where(d => d.TargetAgencyId == agencyId) .Where(d => d.IsActive) .Select(d => d.DiscountPercent) .ToListAsync(); allDiscounts.Add(discount.DiscountPercent); var discountDoesntExceed = DiscountsValidator.DiscountsDontExceedMarkups(allDiscounts, markupFunction); return(discountDoesntExceed.IsSuccess ? Result.Success(discount) : Result.Failure <Discount>("One of activate discounts exceeds markups")); } }
public async Task <Result> Update(int agencyId, int discountId, EditDiscountRequest editDiscountRequest) { return(await Get(agencyId, discountId) .Check(_ => ValidatePercent(editDiscountRequest.DiscountPercent)) .Check(DiscountDoesntExceedMarkups) .BindWithTransaction(_context, discount => Result.Success(discount) .Tap(Update) .Bind(WriteAuditLog))); async Task <Result> DiscountDoesntExceedMarkups(Discount discount) { var markupPolicy = await _context.MarkupPolicies.SingleOrDefaultAsync(x => x.Id == discount.TargetPolicyId); var markupFunction = _templateService.CreateFunction(markupPolicy.TemplateId, markupPolicy.TemplateSettings); var allDiscounts = await _context.Discounts .Where(x => x.TargetPolicyId == markupPolicy.Id) .Where(d => d.TargetAgencyId == agencyId) .Where(d => d.IsActive) .Where(d => d.Id != discountId) // excluding discount we want to edit .Select(d => d.DiscountPercent) .ToListAsync(); allDiscounts.Add(editDiscountRequest.DiscountPercent); return(DiscountsValidator.DiscountsDontExceedMarkups(allDiscounts, markupFunction)); } Task Update(Discount discount) => this.Update(discount, d => { d.DiscountPercent = editDiscountRequest.DiscountPercent; d.Description = editDiscountRequest.Description; }); Task <Result> WriteAuditLog(Discount _) => _managementAuditService.Write(ManagementEventType.DiscountEdit, new DiscountEditEventData(agencyId, editDiscountRequest)); }
public Task <Result> Add(int agencyId, CreateDiscountRequest createDiscountRequest) { return(ValidatePercent(createDiscountRequest.DiscountPercent) .Bind(ValidateTargetMarkup) .Bind(ValidateAgency) .Bind(DiscountsDontExceedMarkups) .BindWithTransaction(_context, () => Result.Success() .Tap(UpdateDiscount) .Bind(WriteAuditLog))); async Task <Result> ValidateTargetMarkup() { var targetMarkup = await _context.MarkupPolicies .SingleOrDefaultAsync(p => p.Id == createDiscountRequest.TargetMarkupId); if (targetMarkup is null) { return(Result.Failure($"Could not find markup policy with id {createDiscountRequest.TargetMarkupId}")); } return(targetMarkup.SubjectScopeType == SubjectMarkupScopeTypes.Global ? Result.Success() : Result.Failure("Cannot apply discount to non-global markup policy")); } async Task <Result> ValidateAgency() => await _context.Agencies.AnyAsync(a => a.Id == agencyId) ? Result.Success() : Result.Failure($"Could not find an agency with id {agencyId}"); async Task <Result> DiscountsDontExceedMarkups() { var markupPolicy = await _context.MarkupPolicies.SingleOrDefaultAsync(x => x.Id == createDiscountRequest.TargetMarkupId); var markupFunction = _templateService.CreateFunction(markupPolicy.TemplateId, markupPolicy.TemplateSettings); var allDiscounts = await _context.Discounts .Where(x => x.TargetPolicyId == markupPolicy.Id) .Where(d => d.TargetAgencyId == agencyId) .Where(d => d.IsActive) .Select(d => d.DiscountPercent) .ToListAsync(); allDiscounts.Add(createDiscountRequest.DiscountPercent); return(DiscountsValidator.DiscountsDontExceedMarkups(allDiscounts, markupFunction)); } Task UpdateDiscount() { var now = _dateTimeProvider.UtcNow(); _context.Discounts.Add(new Discount { DiscountPercent = createDiscountRequest.DiscountPercent, Description = createDiscountRequest.Description, TargetPolicyId = createDiscountRequest.TargetMarkupId, IsActive = true, TargetAgencyId = agencyId, Created = now, Modified = now }); return(_context.SaveChangesAsync()); } Task <Result> WriteAuditLog() => _managementAuditService.Write(ManagementEventType.DiscountCreate, new DiscountCreateEventData(agencyId, createDiscountRequest)); }
public async Task <Result> Modify(int policyId, MarkupPolicySettings settings) { var destinationScopeType = await GetDestinationScopeType(settings.DestinationScopeId); if (destinationScopeType.IsFailure) { return(Result.Failure(destinationScopeType.Error)); } var policy = await _context.MarkupPolicies.SingleOrDefaultAsync(p => p.Id == policyId); if (policy == null) { return(Result.Failure("Could not find policy")); } var(_, isFailure, markupPolicy, error) = await ValidateSettings() .Bind(DiscountsDontExceedMarkups) .Bind(UpdatePolicy) .Tap(p => WriteAuditLog(p, MarkupPolicyEventOperationType.Modified)); if (isFailure) { return(Result.Failure(error)); } return(await UpdateDisplayedMarkupFormula(markupPolicy)); Result ValidateSettings() => _templateService.Validate(settings.TemplateId, settings.TemplateSettings); async Task <Result> DiscountsDontExceedMarkups() { // This check is only applicable to agency scope markups if (policy.SubjectScopeType != SubjectMarkupScopeTypes.Agency) { return(Result.Success()); } var agencyId = int.Parse(policy.SubjectScopeId); var allDiscounts = await _context.Discounts .Where(x => x.IsActive) .Where(x => x.TargetAgencyId == agencyId) .Where(x => x.TargetPolicyId == policy.Id) .Select(x => x.DiscountPercent) .ToListAsync(); var markupFunction = _templateService.CreateFunction(policy.TemplateId, policy.TemplateSettings); return(DiscountsValidator.DiscountsDontExceedMarkups(allDiscounts, markupFunction)); } async Task <Result <MarkupPolicy> > UpdatePolicy() { policy.Description = settings.Description; policy.Order = settings.Order; policy.TemplateId = settings.TemplateId; policy.TemplateSettings = settings.TemplateSettings; policy.Currency = settings.Currency; policy.Modified = _dateTimeProvider.UtcNow(); policy.SubjectScopeId = settings.LocationScopeId; // No SubjectScopeType here because changing its type is not allowed policy.DestinationScopeId = settings.DestinationScopeId; policy.DestinationScopeType = destinationScopeType.Value; var policyData = GetPolicyData(policy); if (policyData.IsFailure) { return(Result.Failure <MarkupPolicy>(policyData.Error)); } var(_, isFailure, error) = await ValidatePolicy(policyData.Value, policy); if (isFailure) { return(Result.Failure <MarkupPolicy>(error)); } _context.Update(policy); await _context.SaveChangesAsync(); return(policy); } }