From 69ecb71cdd98b8de69a06e76efe20e4964f789a2 Mon Sep 17 00:00:00 2001 From: Yelena Shahparonyan Date: Thu, 9 Oct 2025 17:17:53 +0400 Subject: [PATCH] adding commission validation --- src/SharedKernel/SharedKernel.csproj | 67 +++++++++--------- .../Validators/CommissionRuleValidator.cs | 52 ++++++++++++++ .../Files/CommissionRangeValidator.cs | 68 +++++++++++++++++++ .../Validators/ValidatorExtensions.cs | 7 +- 4 files changed, 160 insertions(+), 34 deletions(-) create mode 100644 src/SharedKernel/ValidatorAndMediatR/Validators/CommissionRuleValidator.cs create mode 100644 src/SharedKernel/ValidatorAndMediatR/Validators/Files/CommissionRangeValidator.cs diff --git a/src/SharedKernel/SharedKernel.csproj b/src/SharedKernel/SharedKernel.csproj index 76c2baa..c594d5b 100644 --- a/src/SharedKernel/SharedKernel.csproj +++ b/src/SharedKernel/SharedKernel.csproj @@ -8,7 +8,7 @@ Readme.md Pandatech MIT - 1.8.2 + 1.8.3 Pandatech.SharedKernel Pandatech Shared Kernel Library Pandatech, shared kernel, library, OpenAPI, Swagger, utilities, scalar @@ -18,46 +18,47 @@ - - + + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + diff --git a/src/SharedKernel/ValidatorAndMediatR/Validators/CommissionRuleValidator.cs b/src/SharedKernel/ValidatorAndMediatR/Validators/CommissionRuleValidator.cs new file mode 100644 index 0000000..860a58a --- /dev/null +++ b/src/SharedKernel/ValidatorAndMediatR/Validators/CommissionRuleValidator.cs @@ -0,0 +1,52 @@ +using CommissionCalculator.DTO; +using FluentValidation; +using FluentValidation.Validators; +using SharedKernel.ValidatorAndMediatR.Validators.Files; + +namespace SharedKernel.ValidatorAndMediatR.Validators; +public sealed class CommissionRuleValidator : PropertyValidator +{ + public override string Name => "CommissionRuleValidator"; + + public override bool IsValid(ValidationContext context, CommissionRule? rule) + { + if (rule == null || rule.CommissionRangeConfigs.Count == 0) + { + context.AddFailure("The ranges list cannot be null or empty."); + return false; + } + + if (rule.CommissionRangeConfigs.Any( + r => r is { Type: CommissionType.Percentage, CommissionAmount: < -10 or > 10 })) + { + context.AddFailure( + "For 'Percentage' CommissionType, the CommissionAmount should be between -10 and 10. Commissions over 1000% are not allowed."); + return false; + } + + if (rule.CommissionRangeConfigs.Count == 1) + { + if (rule.CommissionRangeConfigs[0].RangeStart != 0 || rule.CommissionRangeConfigs[0].RangeEnd != 0) + { + context.AddFailure("In case of one range, both 'From' and 'To' should be 0."); + return false; + } + + if (rule.CommissionRangeConfigs[0].MaxCommission != 0 && rule.CommissionRangeConfigs[0].MaxCommission < + rule.CommissionRangeConfigs[0].MinCommission) + { + context.AddFailure("MaxCommission should be greater than or equal to MinCommission."); + return false; + } + + return true; //check + } + else + { + var rangeValidator = new CommissionRangeValidator(); + var rangeValidatorResult = rangeValidator.IsValid(context, rule); + + return true && rangeValidatorResult; + } + } +} diff --git a/src/SharedKernel/ValidatorAndMediatR/Validators/Files/CommissionRangeValidator.cs b/src/SharedKernel/ValidatorAndMediatR/Validators/Files/CommissionRangeValidator.cs new file mode 100644 index 0000000..08e2a25 --- /dev/null +++ b/src/SharedKernel/ValidatorAndMediatR/Validators/Files/CommissionRangeValidator.cs @@ -0,0 +1,68 @@ +using CommissionCalculator.DTO; +using FluentValidation; +using FluentValidation.Validators; + +namespace SharedKernel.ValidatorAndMediatR.Validators.Files; +public sealed class CommissionRangeValidator : PropertyValidator +{ + public override string Name => "CommissionRangeValidator"; + + public override bool IsValid(ValidationContext context, CommissionRule? rule) + { + var startRule = rule!.CommissionRangeConfigs.FirstOrDefault(r => r is { RangeStart: 0, RangeEnd: > 0 }); + if (startRule == null) + { + context.AddFailure("There should be at least one rule where From = 0."); + return false; + } + + if (startRule.MaxCommission != 0 && startRule.MaxCommission < startRule.MinCommission) + { + context.AddFailure("MaxCommission should be greater than or equal to MinCommission."); + return false; + } + + var verifiedRules = 1; + + var lastTo = startRule.RangeEnd; + + while (true) + { + var nextRule = rule.CommissionRangeConfigs.FirstOrDefault(r => r.RangeStart == lastTo); + if (nextRule is null && lastTo != 0) + { + context.AddFailure($"Gap detected. No rule found for 'From = {lastTo}'."); + return false; + } + + if (nextRule is not null && nextRule.RangeStart == nextRule.RangeEnd) + { + context.AddFailure("Invalid rule. 'From' and 'To' cannot be equal."); + return false; + } + + if (nextRule is not null && nextRule.MaxCommission != 0 && nextRule.MaxCommission < nextRule.MinCommission) + { + context.AddFailure("MaxCommission should be greater than or equal to MinCommission."); + return false; + } + + if (lastTo == 0) + { + break; + } + + verifiedRules++; + + lastTo = nextRule!.RangeEnd; + } + + if (verifiedRules != rule.CommissionRangeConfigs.Count) + { + context.AddFailure("There is some nested or gap ranges in the rules."); + return false; + } + + return true; //check + } +} diff --git a/src/SharedKernel/ValidatorAndMediatR/Validators/ValidatorExtensions.cs b/src/SharedKernel/ValidatorAndMediatR/Validators/ValidatorExtensions.cs index 0c2634d..b4c143f 100644 --- a/src/SharedKernel/ValidatorAndMediatR/Validators/ValidatorExtensions.cs +++ b/src/SharedKernel/ValidatorAndMediatR/Validators/ValidatorExtensions.cs @@ -1,4 +1,5 @@ -using FluentValidation; +using CommissionCalculator.DTO; +using FluentValidation; using Microsoft.AspNetCore.Http; using SharedKernel.Helpers; using SharedKernel.ValidatorAndMediatR.Validators.Files; @@ -80,4 +81,8 @@ public static IRuleBuilderOptions IsXssSanitized(this IRuleBuilder { return rb.SetValidator(new FilesMaxCountValidator(maxCount)); } + public static IRuleBuilderOptions ValidateCommissionRule(this IRuleBuilder rule) + { + return rule.SetValidator(new CommissionRuleValidator()); + } } \ No newline at end of file