From 0a36c6ae823931b6b5689f4562f07b4241ff85cb Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Thu, 21 Mar 2024 15:09:55 -0500 Subject: [PATCH 01/22] feat: Validate if the identity document is Ecuadorian The implementation of the algorithm is contained in its own plugin project. --- .../DependencyServicesRegisterer.cs | 11 ++++ .../IdentityDocumentEcuador/GlobalUsings.cs | 5 ++ .../IdentityDocumentValidator.cs | 64 +++++++++++++++++++ .../Plugin.IdentityDocument.Ecuador.csproj | 8 +++ 4 files changed, 88 insertions(+) create mode 100644 src/Plugins/IdentityDocumentEcuador/DependencyServicesRegisterer.cs create mode 100644 src/Plugins/IdentityDocumentEcuador/GlobalUsings.cs create mode 100644 src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs create mode 100644 src/Plugins/IdentityDocumentEcuador/Plugin.IdentityDocument.Ecuador.csproj diff --git a/src/Plugins/IdentityDocumentEcuador/DependencyServicesRegisterer.cs b/src/Plugins/IdentityDocumentEcuador/DependencyServicesRegisterer.cs new file mode 100644 index 00000000..a64856c8 --- /dev/null +++ b/src/Plugins/IdentityDocumentEcuador/DependencyServicesRegisterer.cs @@ -0,0 +1,11 @@ +[assembly: Plugin(typeof(DependencyServicesRegisterer))] + +namespace Plugin.IdentityDocument.Ecuador; + +public class DependencyServicesRegisterer : IDependencyServicesRegisterer +{ + public void RegisterServices(IServiceCollection services, IConfiguration configuration) + { + services.AddSingleton(); + } +} diff --git a/src/Plugins/IdentityDocumentEcuador/GlobalUsings.cs b/src/Plugins/IdentityDocumentEcuador/GlobalUsings.cs new file mode 100644 index 00000000..b270670d --- /dev/null +++ b/src/Plugins/IdentityDocumentEcuador/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using DentallApp.Shared.Interfaces; +global using DentallApp.Shared.Resources.ApiResponses; +global using SimpleResults; +global using CPlugin.Net; +global using Plugin.IdentityDocument.Ecuador; diff --git a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs new file mode 100644 index 00000000..9d33e4ad --- /dev/null +++ b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs @@ -0,0 +1,64 @@ +namespace Plugin.IdentityDocument.Ecuador; + +/// +/// Represents a validator for Ecuadorian identity documents. +/// +/// +/// Link to the algorithm: +/// +public class IdentityDocumentValidator : IIdentityDocumentValidator +{ + public Result IsValid(string document) + { + if (string.IsNullOrWhiteSpace(document)) + return Result.Invalid(Messages.DocumentIsEmpty); + + if (document.Length == 10) + return Result.Invalid(string.Format(Messages.DocumentMaxCharacters, 10)); + + if(IsNotNumeric(document)) + return Result.Invalid(Messages.DocumentMustBeNumeric); + + if(HasInvalidRegionDigit(document)) + return Result.Invalid(Messages.DocumentIsInvalid); + + int verificationDigit = int.Parse(document.Substring(9, 10)); + int total = 0; + foreach(char c in document) + { + int digit = c - '0'; + bool isOdd = digit % 2 == 1; + if (isOdd) + { + int result = digit * 2 > 9 ? digit - 9 : digit; + total += result; + continue; + } + total += digit; + } + + bool isValidDocument = + (total % 10 == 0 && verificationDigit == 0) || + (10 - (total % 10) == verificationDigit); + + return isValidDocument ? + Result.Success() : + Result.Invalid(Messages.DocumentIsInvalid); + } + + private static bool IsNotNumeric(string document) + => document.Where(c => c is < '0' or > '9').Any(); + + private static bool HasInvalidRegionDigit(string document) + => !HasValidRegionDigit(document); + + private static bool HasValidRegionDigit(string document) + { + // The digit of the region is obtained, which are the first two digits. + int regionDigit = int.Parse(document[..2]); + + // It is validated if the region digit exists in Ecuador, which is divided into 24 regions. + // 30 is assigned for Ecuadorians abroad. + return regionDigit is (>= 1 and <= 24) or 30; + } +} diff --git a/src/Plugins/IdentityDocumentEcuador/Plugin.IdentityDocument.Ecuador.csproj b/src/Plugins/IdentityDocumentEcuador/Plugin.IdentityDocument.Ecuador.csproj new file mode 100644 index 00000000..bd13a38c --- /dev/null +++ b/src/Plugins/IdentityDocumentEcuador/Plugin.IdentityDocument.Ecuador.csproj @@ -0,0 +1,8 @@ + + + + Library + Plugin.IdentityDocument.Ecuador + + + From ce48e4315acfacbae5c578bdff7c63d3258cded3 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Thu, 21 Mar 2024 15:11:31 -0500 Subject: [PATCH 02/22] chore: Add new resources --- .../ApiResponses/Messages.Designer.cs | 36 +++++++++++++++++++ .../Resources/ApiResponses/Messages.resx | 12 +++++++ 2 files changed, 48 insertions(+) diff --git a/src/Shared/Resources/ApiResponses/Messages.Designer.cs b/src/Shared/Resources/ApiResponses/Messages.Designer.cs index 70631c97..e25b5ad8 100644 --- a/src/Shared/Resources/ApiResponses/Messages.Designer.cs +++ b/src/Shared/Resources/ApiResponses/Messages.Designer.cs @@ -300,6 +300,42 @@ public static string DirectLineTokenFailed { } } + /// + /// Looks up a localized string similar to El documento de identidad está vacío.. + /// + public static string DocumentIsEmpty { + get { + return ResourceManager.GetString("DocumentIsEmpty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to El documento de identidad es inválido.. + /// + public static string DocumentIsInvalid { + get { + return ResourceManager.GetString("DocumentIsInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to El documento de identidad debe tener {0} caracteres.. + /// + public static string DocumentMaxCharacters { + get { + return ResourceManager.GetString("DocumentMaxCharacters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to El documento de identidad debe ser numérico.. + /// + public static string DocumentMustBeNumeric { + get { + return ResourceManager.GetString("DocumentMustBeNumeric", resourceCulture); + } + } + /// /// Looks up a localized string similar to El correo electrónico no está confirmado.. /// diff --git a/src/Shared/Resources/ApiResponses/Messages.resx b/src/Shared/Resources/ApiResponses/Messages.resx index 485c4f46..aa27321d 100644 --- a/src/Shared/Resources/ApiResponses/Messages.resx +++ b/src/Shared/Resources/ApiResponses/Messages.resx @@ -201,6 +201,18 @@ Error en la llamada a la API del token de Direct Line. + + El documento de identidad está vacío. + + + El documento de identidad es inválido. + + + El documento de identidad debe tener {0} caracteres. + + + El documento de identidad debe ser numérico. + El correo electrónico no está confirmado. From 38a9fa34b60453ced6f42f9cec346bee862c35c6 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Thu, 21 Mar 2024 15:11:58 -0500 Subject: [PATCH 03/22] chore: Add project to solution file --- DentallApp.sln | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/DentallApp.sln b/DentallApp.sln index 50c0742f..c2b47c32 100644 --- a/DentallApp.sln +++ b/DentallApp.sln @@ -19,9 +19,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.ChatBot", "src\Plugi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.ChatBot.IntegrationTests", "tests\ChatBot\Plugin.ChatBot.IntegrationTests.csproj", "{3897DDB9-5C4F-4664-94D7-756A5E673951}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.Twilio.WhatsApp", "src\Plugins\TwilioWhatsApp\Plugin.Twilio.WhatsApp.csproj", "{6B8BD4C1-00A7-429B-A22F-25851E7296B5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.Twilio.WhatsApp", "src\Plugins\TwilioWhatsApp\Plugin.Twilio.WhatsApp.csproj", "{6B8BD4C1-00A7-429B-A22F-25851E7296B5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.SendGrid", "src\Plugins\SendGrid\Plugin.SendGrid.csproj", "{6917AD6C-E337-4DE6-88D8-B0990E9B8D56}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.SendGrid", "src\Plugins\SendGrid\Plugin.SendGrid.csproj", "{6917AD6C-E337-4DE6-88D8-B0990E9B8D56}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.IdentityDocument.Ecuador", "src\Plugins\IdentityDocumentEcuador\Plugin.IdentityDocument.Ecuador.csproj", "{390B0477-73DB-4C71-A1BE-4539E93EF55D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Elements", "Solution Elements", "{D66CD840-8EE9-4697-9FFA-B4E5B0F25D80}" ProjectSection(SolutionItems) = preProject @@ -42,14 +44,6 @@ Global {E354A181-1E6C-4F76-8D99-96E5A6824FC1}.Debug|Any CPU.Build.0 = Debug|Any CPU {E354A181-1E6C-4F76-8D99-96E5A6824FC1}.Release|Any CPU.ActiveCfg = Release|Any CPU {E354A181-1E6C-4F76-8D99-96E5A6824FC1}.Release|Any CPU.Build.0 = Release|Any CPU - {EACB8B54-AAFE-4A46-A1D9-1FB23ADDA41C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EACB8B54-AAFE-4A46-A1D9-1FB23ADDA41C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EACB8B54-AAFE-4A46-A1D9-1FB23ADDA41C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EACB8B54-AAFE-4A46-A1D9-1FB23ADDA41C}.Release|Any CPU.Build.0 = Release|Any CPU - {BFD8D9F8-AEF4-4661-B0DC-6D79F84F718E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BFD8D9F8-AEF4-4661-B0DC-6D79F84F718E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BFD8D9F8-AEF4-4661-B0DC-6D79F84F718E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BFD8D9F8-AEF4-4661-B0DC-6D79F84F718E}.Release|Any CPU.Build.0 = Release|Any CPU {1B8756B1-A59A-4724-B757-01AAECADF43C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1B8756B1-A59A-4724-B757-01AAECADF43C}.Debug|Any CPU.Build.0 = Debug|Any CPU {1B8756B1-A59A-4724-B757-01AAECADF43C}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -66,6 +60,14 @@ Global {BE6318A1-900B-4E8E-8AAE-C391F881C844}.Debug|Any CPU.Build.0 = Debug|Any CPU {BE6318A1-900B-4E8E-8AAE-C391F881C844}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE6318A1-900B-4E8E-8AAE-C391F881C844}.Release|Any CPU.Build.0 = Release|Any CPU + {EACB8B54-AAFE-4A46-A1D9-1FB23ADDA41C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EACB8B54-AAFE-4A46-A1D9-1FB23ADDA41C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EACB8B54-AAFE-4A46-A1D9-1FB23ADDA41C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EACB8B54-AAFE-4A46-A1D9-1FB23ADDA41C}.Release|Any CPU.Build.0 = Release|Any CPU + {BFD8D9F8-AEF4-4661-B0DC-6D79F84F718E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFD8D9F8-AEF4-4661-B0DC-6D79F84F718E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFD8D9F8-AEF4-4661-B0DC-6D79F84F718E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFD8D9F8-AEF4-4661-B0DC-6D79F84F718E}.Release|Any CPU.Build.0 = Release|Any CPU {3897DDB9-5C4F-4664-94D7-756A5E673951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3897DDB9-5C4F-4664-94D7-756A5E673951}.Debug|Any CPU.Build.0 = Debug|Any CPU {3897DDB9-5C4F-4664-94D7-756A5E673951}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -78,6 +80,10 @@ Global {6917AD6C-E337-4DE6-88D8-B0990E9B8D56}.Debug|Any CPU.Build.0 = Debug|Any CPU {6917AD6C-E337-4DE6-88D8-B0990E9B8D56}.Release|Any CPU.ActiveCfg = Release|Any CPU {6917AD6C-E337-4DE6-88D8-B0990E9B8D56}.Release|Any CPU.Build.0 = Release|Any CPU + {390B0477-73DB-4C71-A1BE-4539E93EF55D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {390B0477-73DB-4C71-A1BE-4539E93EF55D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {390B0477-73DB-4C71-A1BE-4539E93EF55D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {390B0477-73DB-4C71-A1BE-4539E93EF55D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 06450c86af65390ed70e5e5dfa7ca681109c0aac Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Thu, 21 Mar 2024 15:12:52 -0500 Subject: [PATCH 04/22] feat: Create validation rule using Fluent Validation --- .../ValidationRules/DocumentValidator.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/Shared/ValidationRules/DocumentValidator.cs diff --git a/src/Shared/ValidationRules/DocumentValidator.cs b/src/Shared/ValidationRules/DocumentValidator.cs new file mode 100644 index 00000000..be965a1b --- /dev/null +++ b/src/Shared/ValidationRules/DocumentValidator.cs @@ -0,0 +1,28 @@ +namespace DentallApp.Shared.ValidationRules; + +public static class DocumentValidator +{ + public static IRuleBuilderOptions MustBeValidDocument( + this IRuleBuilder ruleBuilder, + IIdentityDocumentValidator documentValidator) + { + return ruleBuilder.Must((rootObject, document, context) => + { + if (string.IsNullOrWhiteSpace(document)) + { + context.AddFailure(Messages.DocumentIsEmpty); + return false; + } + + Result result = documentValidator.IsValid(document); + if (result.IsSuccess) + return true; + + context.AddFailure(result.Message); + foreach (string error in result.Errors) + context.AddFailure(error); + + return false; + }); + } +} From 6d5b9085200608a81e58334c72b3043832da9703 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Thu, 21 Mar 2024 15:16:23 -0500 Subject: [PATCH 05/22] Create FakeIdentityDocument type This is the default implementation in case no plugin registers its own implementation. --- src/Infrastructure/Services/FakeIdentityDocument.cs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/Infrastructure/Services/FakeIdentityDocument.cs diff --git a/src/Infrastructure/Services/FakeIdentityDocument.cs b/src/Infrastructure/Services/FakeIdentityDocument.cs new file mode 100644 index 00000000..21641eef --- /dev/null +++ b/src/Infrastructure/Services/FakeIdentityDocument.cs @@ -0,0 +1,6 @@ +namespace DentallApp.Infrastructure.Services; + +public class FakeIdentityDocument : IIdentityDocumentValidator +{ + public Result IsValid(string document) => Result.Success(); +} From ab062ec0e10bd36a6af094673f1810894085dea0 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Thu, 21 Mar 2024 15:16:58 -0500 Subject: [PATCH 06/22] refactor: Add fake type to the service collection --- src/HostApplication/PluginStartup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/HostApplication/PluginStartup.cs b/src/HostApplication/PluginStartup.cs index 5a7ed95b..f8af1fab 100644 --- a/src/HostApplication/PluginStartup.cs +++ b/src/HostApplication/PluginStartup.cs @@ -17,5 +17,6 @@ public static void ConfigureServices(WebApplicationBuilder builder) // These services are only added when no plugin registers its own implementation. builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); + builder.Services.TryAddSingleton(); } } From d9c908d41e56f379b1f1f904cfefc87488fedbcd Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Thu, 21 Mar 2024 15:18:49 -0500 Subject: [PATCH 07/22] feat: Create an interface to validate whether the identity document is valid --- src/Shared/Interfaces/IIdentityDocumentValidator.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/Shared/Interfaces/IIdentityDocumentValidator.cs diff --git a/src/Shared/Interfaces/IIdentityDocumentValidator.cs b/src/Shared/Interfaces/IIdentityDocumentValidator.cs new file mode 100644 index 00000000..e56f9841 --- /dev/null +++ b/src/Shared/Interfaces/IIdentityDocumentValidator.cs @@ -0,0 +1,13 @@ +namespace DentallApp.Shared.Interfaces; + +/// +/// Represents a validator to validate identity documents. +/// +public interface IIdentityDocumentValidator +{ + /// + /// Checks if an identity document is valid. + /// + /// The document to validate. + Result IsValid(string document); +} From 8abe6c5c453e0d1b51c8069af7ba531a6ce4f072 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Fri, 22 Mar 2024 18:05:34 -0500 Subject: [PATCH 08/22] fix: Corrected conditional --- .../IdentityDocumentEcuador/IdentityDocumentValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs index 9d33e4ad..a8f75ac6 100644 --- a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs +++ b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs @@ -13,7 +13,7 @@ public Result IsValid(string document) if (string.IsNullOrWhiteSpace(document)) return Result.Invalid(Messages.DocumentIsEmpty); - if (document.Length == 10) + if (document.Length != 10) return Result.Invalid(string.Format(Messages.DocumentMaxCharacters, 10)); if(IsNotNumeric(document)) From d36c1bb7f389a466351def520df446ae6936a171 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Fri, 22 Mar 2024 18:17:51 -0500 Subject: [PATCH 09/22] fix: Avoid IndexOutOfRangeException --- .../IdentityDocumentEcuador/IdentityDocumentValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs index a8f75ac6..76168910 100644 --- a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs +++ b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs @@ -22,7 +22,7 @@ public Result IsValid(string document) if(HasInvalidRegionDigit(document)) return Result.Invalid(Messages.DocumentIsInvalid); - int verificationDigit = int.Parse(document.Substring(9, 10)); + int verificationDigit = int.Parse(document[^1].ToString()); int total = 0; foreach(char c in document) { From 8598f3fdeb60286e9a508b607c9baa8494bd7f42 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Fri, 22 Mar 2024 20:27:28 -0500 Subject: [PATCH 10/22] fix: Change identity document verification algorithm The algorithm had been implemented incorrectly. See https://www.skypack.dev/view/udv-ec --- .../IdentityDocumentValidator.cs | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs index 76168910..f87aa176 100644 --- a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs +++ b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs @@ -4,7 +4,7 @@ /// Represents a validator for Ecuadorian identity documents. /// /// -/// Link to the algorithm: +/// Link to the algorithm: /// public class IdentityDocumentValidator : IIdentityDocumentValidator { @@ -24,17 +24,16 @@ public Result IsValid(string document) int verificationDigit = int.Parse(document[^1].ToString()); int total = 0; - foreach(char c in document) + bool isOddPosition = false; + // The verification digit is not considered. + int len = document.Length - 1; + for (int i = 0; i < len; i++) { - int digit = c - '0'; - bool isOdd = digit % 2 == 1; - if (isOdd) - { - int result = digit * 2 > 9 ? digit - 9 : digit; - total += result; - continue; - } - total += digit; + isOddPosition = !isOddPosition; + int coefficient = isOddPosition ? 2 : 1; + int digit = (document[i] - '0') * coefficient; + int result = digit > 9 ? digit - 9 : digit; + total += result; } bool isValidDocument = From bb8f3cd32948fe54dd18200581665b39ff7298e2 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Fri, 22 Mar 2024 20:28:03 -0500 Subject: [PATCH 11/22] chore: Add project reference --- tests/UnitTests/DentallApp.UnitTests.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/UnitTests/DentallApp.UnitTests.csproj b/tests/UnitTests/DentallApp.UnitTests.csproj index 75b2c2dc..2bf78051 100644 --- a/tests/UnitTests/DentallApp.UnitTests.csproj +++ b/tests/UnitTests/DentallApp.UnitTests.csproj @@ -21,6 +21,7 @@ + From 249b8a7a3e1ccf0a34bca6e7b230251235363aee Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Fri, 22 Mar 2024 20:28:16 -0500 Subject: [PATCH 12/22] chore: Update global usings --- tests/UnitTests/GlobalUsings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/UnitTests/GlobalUsings.cs b/tests/UnitTests/GlobalUsings.cs index ff723664..b8c6e701 100644 --- a/tests/UnitTests/GlobalUsings.cs +++ b/tests/UnitTests/GlobalUsings.cs @@ -1,7 +1,6 @@ global using System.Collections; global using System.Text.Json; global using System.Text.Json.Serialization; -global using System.Security.Claims; global using NUnit.Framework; global using FluentAssertions; global using FluentValidation; @@ -9,6 +8,7 @@ global using Microsoft.Bot.Schema; global using Telerik.JustMock; global using DotEnv.Core; +global using SimpleResults; global using DentallApp.Core.Appointments.UseCases; global using DentallApp.Core.Appointments.UseCases.GetAvailableHours; @@ -25,7 +25,6 @@ global using DentallApp.Shared.Resources.Weekdays; global using DentallApp.Shared.Resources.ApiResponses; global using DentallApp.Shared.Reasons; -global using DentallApp.Shared.Constants; global using DentallApp.Shared.Configuration; global using DentallApp.Shared.ValidationRules; @@ -33,3 +32,4 @@ global using Plugin.ChatBot.Models; global using Plugin.ChatBot.DirectLine; global using Plugin.ChatBot.DirectLine.Services; +global using Plugin.IdentityDocument.Ecuador; From 4692bc487827b408527899e4826b21c5d70c7598 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Fri, 22 Mar 2024 20:31:23 -0500 Subject: [PATCH 13/22] refactor: Add private members at the end of the file --- .../ValidationRules/PasswordValidatorTests.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/UnitTests/Shared/ValidationRules/PasswordValidatorTests.cs b/tests/UnitTests/Shared/ValidationRules/PasswordValidatorTests.cs index 304bdb2e..2907c926 100644 --- a/tests/UnitTests/Shared/ValidationRules/PasswordValidatorTests.cs +++ b/tests/UnitTests/Shared/ValidationRules/PasswordValidatorTests.cs @@ -2,20 +2,6 @@ public class PasswordValidatorTests { - private class User - { - public string Password { get; init; } - } - - private class UserValidator : AbstractValidator - { - public UserValidator() - { - RuleFor(user => user.Password) - .MustBeSecurePassword(); - } - } - [TestCase("1234")] [TestCase("D234")] [TestCase("DD34")] @@ -63,4 +49,18 @@ public void ShouldHaveErrorWhenPasswordIsEmpty(string password) var result = validator.TestValidate(model); result.ShouldHaveValidationErrorFor(user => user.Password); } + + private class User + { + public string Password { get; init; } + } + + private class UserValidator : AbstractValidator + { + public UserValidator() + { + RuleFor(user => user.Password) + .MustBeSecurePassword(); + } + } } From b6165727dda5e5e703fd013554d27e6a33cd9980 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Fri, 22 Mar 2024 20:32:39 -0500 Subject: [PATCH 14/22] test: Add unit tests to validate identity documents --- .../IdentityDocumentValidatorTests.cs | 110 ++++++++++++++++++ .../ValidationRules/DocumentValidatorTests.cs | 47 ++++++++ 2 files changed, 157 insertions(+) create mode 100644 tests/UnitTests/Plugins/IdentityDocumentEcuador/IdentityDocumentValidatorTests.cs create mode 100644 tests/UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs diff --git a/tests/UnitTests/Plugins/IdentityDocumentEcuador/IdentityDocumentValidatorTests.cs b/tests/UnitTests/Plugins/IdentityDocumentEcuador/IdentityDocumentValidatorTests.cs new file mode 100644 index 00000000..1540166d --- /dev/null +++ b/tests/UnitTests/Plugins/IdentityDocumentEcuador/IdentityDocumentValidatorTests.cs @@ -0,0 +1,110 @@ +namespace UnitTests.Plugins.IdentityDocumentEcuador; + +public class IdentityDocumentValidatorTests +{ + [TestCase("")] + [TestCase(" ")] + [TestCase(null)] + public void IsValid_WhenDocumentIsEmpty_ShouldReturnsInvalidResult(string document) + { + // Arrange + var validator = new IdentityDocumentValidator(); + var expectedMessage = Messages.DocumentIsEmpty; + + // Act + Result result = validator.IsValid(document); + + // Asserts + result.IsSuccess.Should().BeFalse(); + result.Message.Should().Be(expectedMessage); + } + + [TestCase("12345")] + [TestCase("12345678910")] + public void IsValid_WhenDocumentDoesNotHaveTenCharacters_ShouldReturnsInvalidResult(string document) + { + // Arrange + var validator = new IdentityDocumentValidator(); + var expectedMessage = string.Format(Messages.DocumentMaxCharacters, 10); + + // Act + Result result = validator.IsValid(document); + + // Asserts + result.IsSuccess.Should().BeFalse(); + result.Message.Should().Be(expectedMessage); + } + + [TestCase("092361170a")] + [TestCase("09236A1701")] + [TestCase("09236$#a0-")] + public void IsValid_WhenDocumentIsNotNumeric_ShouldReturnsInvalidResult(string document) + { + // Arrange + var validator = new IdentityDocumentValidator(); + var expectedMessage = Messages.DocumentMustBeNumeric; + + // Act + Result result = validator.IsValid(document); + + // Asserts + result.IsSuccess.Should().BeFalse(); + result.Message.Should().Be(expectedMessage); + } + + [TestCase("0023611701")] + [TestCase("2523611701")] + [TestCase("2923611701")] + [TestCase("3123611701")] + [TestCase("0104132817")] + [TestCase("0108875282")] + [TestCase("0100704434")] + [TestCase("0100201244")] + [TestCase("0107304047")] + [TestCase("0106784415")] + [TestCase("0100194636")] + [TestCase("0106354840")] + [TestCase("0100924960")] + [TestCase("1404840463")] + [TestCase("1313821924")] + public void IsValid_WhenDocumentIsInvalid_ShouldReturnsInvalidResult(string document) + { + // Arrange + var validator = new IdentityDocumentValidator(); + var expectedMessage = Messages.DocumentIsInvalid; + + // Act + Result result = validator.IsValid(document); + + // Asserts + result.IsSuccess.Should().BeFalse(); + result.Message.Should().Be(expectedMessage); + } + + [TestCase("1713175071")] + [TestCase("1710034065")] + [TestCase("0923611701")] + [TestCase("0102813417")] + [TestCase("0105287882")] + [TestCase("0104470034")] + [TestCase("0101220044")] + [TestCase("0104030747")] + [TestCase("0104478615")] + [TestCase("0104619036")] + [TestCase("0104835640")] + [TestCase("0104992060")] + [TestCase("1400484463")] + [TestCase("1500449861")] + [TestCase("1311982324")] + public void IsValid_WhenDocumentIsValid_ShouldReturnsSuccessResult(string document) + { + // Arrange + var validator = new IdentityDocumentValidator(); + + // Act + Result result = validator.IsValid(document); + + // Assert + result.IsSuccess.Should().BeTrue(); + } +} diff --git a/tests/UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs b/tests/UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs new file mode 100644 index 00000000..a187b722 --- /dev/null +++ b/tests/UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs @@ -0,0 +1,47 @@ +namespace UnitTests.Shared.ValidationRules; + +public class DocumentValidatorTests +{ + [Test] + public void ShouldHaveErrorWhenDocumentIsInvalid() + { + var userValidator = new UserValidator(new IdentityDocumentValidator()); + var model = new User { Document = "2523611701" }; + var result = userValidator.TestValidate(model); + result.ShouldHaveValidationErrorFor(user => user.Document); + } + + [Test] + public void ShouldNotHaveErrorWhenDocumentIsValid() + { + var userValidator = new UserValidator(new IdentityDocumentValidator()); + var model = new User { Document = "1311982324" }; + var result = userValidator.TestValidate(model); + result.ShouldNotHaveValidationErrorFor(user => user.Document); + } + + [TestCase("")] + [TestCase(" ")] + [TestCase(null)] + public void ShouldHaveErrorWhenDocumentIsEmpty(string document) + { + var userValidator = new UserValidator(new IdentityDocumentValidator()); + var model = new User { Document = document }; + var result = userValidator.TestValidate(model); + result.ShouldHaveValidationErrorFor(user => user.Document); + } + + private class User + { + public string Document { get; init; } + } + + private class UserValidator : AbstractValidator + { + public UserValidator(IIdentityDocumentValidator documentValidator) + { + RuleFor(user => user.Document) + .MustBeValidDocument(documentValidator); + } + } +} From 3916e5f3290d15bcea5fa145c12b713fe8c64f8a Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 23 Mar 2024 08:59:51 -0500 Subject: [PATCH 15/22] refactor: Add extension method to convert to int --- .../IdentityDocumentEcuador/IdentityDocumentValidator.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs index f87aa176..b8ff06e2 100644 --- a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs +++ b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs @@ -22,7 +22,7 @@ public Result IsValid(string document) if(HasInvalidRegionDigit(document)) return Result.Invalid(Messages.DocumentIsInvalid); - int verificationDigit = int.Parse(document[^1].ToString()); + int verificationDigit = document[^1].ToInt(); int total = 0; bool isOddPosition = false; // The verification digit is not considered. @@ -31,7 +31,7 @@ public Result IsValid(string document) { isOddPosition = !isOddPosition; int coefficient = isOddPosition ? 2 : 1; - int digit = (document[i] - '0') * coefficient; + int digit = document[i].ToInt() * coefficient; int result = digit > 9 ? digit - 9 : digit; total += result; } @@ -61,3 +61,8 @@ private static bool HasValidRegionDigit(string document) return regionDigit is (>= 1 and <= 24) or 30; } } + +public static class CharExtensions +{ + public static int ToInt(this char c) => c - '0'; +} From 3685f33d3cd73db8cb36a8716170e09ef57c06d8 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 23 Mar 2024 09:02:47 -0500 Subject: [PATCH 16/22] refactor: Rename validation rule --- src/Shared/ValidationRules/DocumentValidator.cs | 2 +- .../UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Shared/ValidationRules/DocumentValidator.cs b/src/Shared/ValidationRules/DocumentValidator.cs index be965a1b..1826e142 100644 --- a/src/Shared/ValidationRules/DocumentValidator.cs +++ b/src/Shared/ValidationRules/DocumentValidator.cs @@ -2,7 +2,7 @@ public static class DocumentValidator { - public static IRuleBuilderOptions MustBeValidDocument( + public static IRuleBuilderOptions MustBeValidIdentityDocument( this IRuleBuilder ruleBuilder, IIdentityDocumentValidator documentValidator) { diff --git a/tests/UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs b/tests/UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs index a187b722..13b6138c 100644 --- a/tests/UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs +++ b/tests/UnitTests/Shared/ValidationRules/DocumentValidatorTests.cs @@ -41,7 +41,7 @@ private class UserValidator : AbstractValidator public UserValidator(IIdentityDocumentValidator documentValidator) { RuleFor(user => user.Document) - .MustBeValidDocument(documentValidator); + .MustBeValidIdentityDocument(documentValidator); } } } From e5e4a4e60c4eeb397a16c0561db46b1f1d940126 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 23 Mar 2024 09:10:08 -0500 Subject: [PATCH 17/22] chore: Update docker file to include new plugin --- Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Dockerfile b/Dockerfile index eefcb3b0..39668775 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,7 @@ COPY ["src/Plugins/AppointmentReminders/*.csproj", "src/Plugins/AppointmentRemin COPY ["src/Plugins/ChatBot/*.csproj", "src/Plugins/ChatBot/"] COPY ["src/Plugins/SendGrid/*.csproj", "src/Plugins/SendGrid/"] COPY ["src/Plugins/TwilioWhatsApp/*.csproj", "src/Plugins/TwilioWhatsApp/"] +COPY ["src/Plugins/IdentityDocumentEcuador/*.csproj", "src/Plugins/IdentityDocumentEcuador/"] COPY ["src/Plugins/*.props", "src/Plugins/"] WORKDIR /app/src/Plugins/AppointmentReminders RUN dotnet restore @@ -29,6 +30,8 @@ WORKDIR /app/src/Plugins/SendGrid RUN dotnet restore WORKDIR /app/src/Plugins/TwilioWhatsApp RUN dotnet restore +WORKDIR /app/src/Plugins/IdentityDocumentEcuador +RUN dotnet restore # Copy everything else and build plugins COPY ["src/Shared/", "/app/src/Shared/"] @@ -41,6 +44,8 @@ WORKDIR /app/src/Plugins/SendGrid RUN dotnet build -c Release --no-restore WORKDIR /app/src/Plugins/TwilioWhatsApp RUN dotnet build -c Release --no-restore +WORKDIR /app/src/Plugins/IdentityDocumentEcuador +RUN dotnet build -c Release --no-restore # Copy everything else and build app COPY ["src/", "/app/src/"] From 0e553fc2d471a7be3eeb5ff5ef2e8cedad70db74 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 23 Mar 2024 09:14:09 -0500 Subject: [PATCH 18/22] chore: Update architecture diagram --- diagrams/general-architecture.png | Bin 807219 -> 827134 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/diagrams/general-architecture.png b/diagrams/general-architecture.png index 3ac6e20db8d583e2fd663110b0033aec661d2b8f..88e2808f970606f4951864612ef440d4591709a2 100644 GIT binary patch delta 58198 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 f8Q_6x;B~MQiedWn Date: Sat, 23 Mar 2024 09:39:34 -0500 Subject: [PATCH 19/22] Update README.md --- README.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6e3f4d63..cc057213 100644 --- a/README.md +++ b/README.md @@ -209,13 +209,15 @@ Request body: ### General architecture
-More details +Show diagram ![general-architecture](https://github.com/DentallApp/back-end/blob/dev/diagrams/general-architecture.png)
-#### Overview of each component +
+More details + - **Host Application.** Contains everything needed to run the application. It represents the entry point of the application. This layer performs other tasks such as: - Load plugins from a configuration file (.env) using the library called [CPlugin.Net](https://github.com/MrDave1999/CPlugin.Net). @@ -256,24 +258,33 @@ Request body: - **Twilio WhatsApp.** It is a plugin that allows to send messages by whatsapp in cases such as: - When an appointment is scheduled from the chatbot, the user is sent the appointment information to whatsapp. - When an employee needs to cancel an appointment, he/she should notify patients by whatsapp. +- **IdentityDocument.Ecuador.** It is a plugin that allows to validate identity documents registered in Ecuador. + This plugin uses an [algorithm](https://www.skypack.dev/view/udv-ec) to verify if the identity document is valid or not. + +
### Core layer
-More details +Show diagram ![core-layer](https://github.com/DentallApp/back-end/blob/dev/diagrams/core-layer.png)
+
+More details + The above diagram describes in more detail which feature modules are contained in the core layer. In the presented diagram it can be identified that the feature modules are not coupled to each other, the purpose of this is not to cause a [dependency hell](https://en.wikipedia.org/wiki/Dependency_hell), in order to maintain a dependency graph that is as simple as possible. The purpose is to make it easier to understand the parts of the backend application. +
+ ### Relational model
-More details +Show diagram ![relational-model](https://github.com/DentallApp/back-end/blob/dev/diagrams/relational-model.png) From 969753a3be0ba7415ef13fbe8433072634422a71 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 23 Mar 2024 09:53:17 -0500 Subject: [PATCH 20/22] feat: Invoke rule to validate identity documents --- src/Core/Dependents/UseCases/Create.cs | 5 +++-- src/Core/Persons/UseCases/Create.cs | 5 +++-- src/Core/Security/Employees/UseCases/Create.cs | 5 +++-- src/Core/Security/Employees/UseCases/UpdateAnyEmployee.cs | 5 +++-- src/Core/Security/Users/UseCases/Create.cs | 5 +++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Core/Dependents/UseCases/Create.cs b/src/Core/Dependents/UseCases/Create.cs index e63bc38b..e44df7cb 100644 --- a/src/Core/Dependents/UseCases/Create.cs +++ b/src/Core/Dependents/UseCases/Create.cs @@ -35,9 +35,10 @@ public Dependent MapToDependent(int userId) public class CreateDependentValidator : AbstractValidator { - public CreateDependentValidator() + public CreateDependentValidator(IIdentityDocumentValidator documentValidator) { - RuleFor(request => request.Document).NotEmpty(); + RuleFor(request => request.Document) + .MustBeValidIdentityDocument(documentValidator); RuleFor(request => request.Names).NotEmpty(); RuleFor(request => request.LastNames).NotEmpty(); RuleFor(request => request.CellPhone).NotEmpty(); diff --git a/src/Core/Persons/UseCases/Create.cs b/src/Core/Persons/UseCases/Create.cs index 601e6d4a..57472acd 100644 --- a/src/Core/Persons/UseCases/Create.cs +++ b/src/Core/Persons/UseCases/Create.cs @@ -24,9 +24,10 @@ public class CreatePersonRequest public class CreatePersonValidator : AbstractValidator { - public CreatePersonValidator() + public CreatePersonValidator(IIdentityDocumentValidator documentValidator) { - RuleFor(request => request.Document).NotEmpty(); + RuleFor(request => request.Document) + .MustBeValidIdentityDocument(documentValidator); RuleFor(request => request.Names).NotEmpty(); RuleFor(request => request.LastNames).NotEmpty(); RuleFor(request => request.CellPhone).NotEmpty(); diff --git a/src/Core/Security/Employees/UseCases/Create.cs b/src/Core/Security/Employees/UseCases/Create.cs index 107e2335..1aba09bc 100644 --- a/src/Core/Security/Employees/UseCases/Create.cs +++ b/src/Core/Security/Employees/UseCases/Create.cs @@ -48,13 +48,14 @@ public Employee MapToEmployee(string password) public class CreateEmployeeValidator : AbstractValidator { - public CreateEmployeeValidator() + public CreateEmployeeValidator(IIdentityDocumentValidator documentValidator) { RuleFor(request => request.UserName) .NotEmpty() .EmailAddress(); RuleFor(request => request.Password).MustBeSecurePassword(); - RuleFor(request => request.Document).NotEmpty(); + RuleFor(request => request.Document) + .MustBeValidIdentityDocument(documentValidator); RuleFor(request => request.Names).NotEmpty(); RuleFor(request => request.LastNames).NotEmpty(); RuleFor(request => request.CellPhone).NotEmpty(); diff --git a/src/Core/Security/Employees/UseCases/UpdateAnyEmployee.cs b/src/Core/Security/Employees/UseCases/UpdateAnyEmployee.cs index 4cd12b06..8ffc4028 100644 --- a/src/Core/Security/Employees/UseCases/UpdateAnyEmployee.cs +++ b/src/Core/Security/Employees/UseCases/UpdateAnyEmployee.cs @@ -36,13 +36,14 @@ public void MapToEmployee(Employee employee) public class UpdateAnyEmployeeValidator : AbstractValidator { - public UpdateAnyEmployeeValidator() + public UpdateAnyEmployeeValidator(IIdentityDocumentValidator documentValidator) { RuleFor(request => request.Email) .NotEmpty() .EmailAddress(); RuleFor(request => request.Password).MustBeSecurePassword(); - RuleFor(request => request.Document).NotEmpty(); + RuleFor(request => request.Document) + .MustBeValidIdentityDocument(documentValidator); RuleFor(request => request.Names).NotEmpty(); RuleFor(request => request.LastNames).NotEmpty(); RuleFor(request => request.CellPhone).NotEmpty(); diff --git a/src/Core/Security/Users/UseCases/Create.cs b/src/Core/Security/Users/UseCases/Create.cs index c7528946..483d2731 100644 --- a/src/Core/Security/Users/UseCases/Create.cs +++ b/src/Core/Security/Users/UseCases/Create.cs @@ -35,13 +35,14 @@ public User MapToUser(string password) public class CreateBasicUserValidator : AbstractValidator { - public CreateBasicUserValidator() + public CreateBasicUserValidator(IIdentityDocumentValidator documentValidator) { RuleFor(request => request.UserName) .NotEmpty() .EmailAddress(); RuleFor(request => request.Password).MustBeSecurePassword(); - RuleFor(request => request.Document).NotEmpty(); + RuleFor(request => request.Document) + .MustBeValidIdentityDocument(documentValidator); RuleFor(request => request.Names).NotEmpty(); RuleFor(request => request.LastNames).NotEmpty(); RuleFor(request => request.CellPhone).NotEmpty(); From 4e4270f9c300ba4fd7dbae18d9866046c5612a90 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 23 Mar 2024 10:15:36 -0500 Subject: [PATCH 21/22] refactor: Rename variable to isEvenPosition --- .../IdentityDocumentEcuador/IdentityDocumentValidator.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs index b8ff06e2..eddf377f 100644 --- a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs +++ b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs @@ -24,13 +24,13 @@ public Result IsValid(string document) int verificationDigit = document[^1].ToInt(); int total = 0; - bool isOddPosition = false; + bool isEvenPosition = false; // The verification digit is not considered. int len = document.Length - 1; for (int i = 0; i < len; i++) { - isOddPosition = !isOddPosition; - int coefficient = isOddPosition ? 2 : 1; + isEvenPosition = !isEvenPosition; + int coefficient = isEvenPosition ? 2 : 1; int digit = document[i].ToInt() * coefficient; int result = digit > 9 ? digit - 9 : digit; total += result; From 60aaa9333558f848ae5e3ca5bc653a2c90d36c41 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 23 Mar 2024 10:18:23 -0500 Subject: [PATCH 22/22] refactor: Rename iterator variable --- .../IdentityDocumentEcuador/IdentityDocumentValidator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs index eddf377f..b93d3066 100644 --- a/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs +++ b/src/Plugins/IdentityDocumentEcuador/IdentityDocumentValidator.cs @@ -27,11 +27,11 @@ public Result IsValid(string document) bool isEvenPosition = false; // The verification digit is not considered. int len = document.Length - 1; - for (int i = 0; i < len; i++) + for (int position = 0; position < len; position++) { isEvenPosition = !isEvenPosition; int coefficient = isEvenPosition ? 2 : 1; - int digit = document[i].ToInt() * coefficient; + int digit = document[position].ToInt() * coefficient; int result = digit > 9 ? digit - 9 : digit; total += result; }