diff --git a/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs b/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs new file mode 100644 index 00000000..a711d31e --- /dev/null +++ b/Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs @@ -0,0 +1,103 @@ +using Bogus.Extensions.Chile; +using FluentAssertions; +using System; +using System.Text.RegularExpressions; +using Xunit; + +namespace Bogus.Tests.ExtensionTests +{ + public class ChileanRutExtensionTest + { + + [Fact] + public void ChileanRutExtension_Should_BeValid_When_UsingDotFormat() + { + // Arrange + var faker = new Faker() + .RuleFor(p => p.Rut, f => f.Person.Rut(true)); + + // Act + var person = faker.Generate(); + + // Assert + InternalValidationRutHelper.IsRutValid(person.Rut).Should().Be(true); + } + + [Fact] + public void ChileanRutExtension_Should_BeValid_When_NotUsingDotFormat() + { + // Arrange + var faker = new Faker() + .RuleFor(p => p.Rut, f => f.Person.Rut(false)); + + // Act + var person = faker.Generate(); + + // Assert + InternalValidationRutHelper.IsRutValid(person.Rut).Should().Be(true); + } + + private class Person + { + internal string Rut { get; set; } = ""; + } + } + + internal static class InternalValidationRutHelper + { + internal static bool IsRutValid(string rut) + { + if (string.IsNullOrEmpty(rut)) + return false; + + rut = rut.Replace(".", ""); + + var expresion = new Regex("^([0-9]+-[0-9K])$"); + string dv = rut.Substring(rut.Length - 1, 1); + if (!expresion.IsMatch(rut)) + { + return false; + } + char[] charCorte = { '-' }; + string[] rutTemp = rut.Split(charCorte); + if (dv != Digito(int.Parse(rutTemp[0]))) + { + return false; + } + return true; + } + + private static string Digito(int rut) + { + if (rut < 1000000 || rut > 99999999) + throw new ArgumentOutOfRangeException($"The provided integer {nameof(rut)} is outside of the range between 1000000 and 99999999"); + + int suma = 0; + int multiplicador = 1; + + while (rut != 0) + { + multiplicador++; + if (multiplicador == 8) + multiplicador = 2; + suma += (rut % 10) * multiplicador; + rut /= 10; + } + + suma = 11 - (suma % 11); + + if (suma == 11) + { + return "0"; + } + else if (suma == 10) + { + return "K"; + } + else + { + return suma.ToString(); + } + } + } +} \ No newline at end of file diff --git a/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs new file mode 100644 index 00000000..2958469e --- /dev/null +++ b/Source/Bogus/Extensions/Chile/ExtensionsForChile.cs @@ -0,0 +1,92 @@ +using System; +using Bogus.DataSets; + +namespace Bogus.Extensions.Chile +{ + /// + /// API extensions specific for a geographical location. + /// + public static class ExtensionsForChile + { + /// + /// Generates a valid Chilean RUT for a Person (Rol Unico Tributario) + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// A string representation for a valid Chilean RUT (Rol Unico Tributario) + public static string Rut(this Person person, bool dotFormat = false) + { + return GenerateChileanId(dotFormat); + } + + /// + /// Generates a valid Chilean RUT for a Company (Rol Unico Tributario) + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// A string representation for a valid Chilean RUT (Rol Unico Tributario) + + public static string Rut(this Company company, bool dotFormat = true) + { + return GenerateChileanId(dotFormat); + } + + /// + /// A general Chilean ID generator + /// + /// Use the thousands separator for the Chilean RUT (11.111.111-1) + /// + private static string GenerateChileanId(bool dotFormat = true) + { + Random rnd = new(); + int num = rnd.Next(1000000, 99999999); + + string dig = Digito(num); + + if (dotFormat) + { + var rut = string.Format("{0:0,0}", num); + return $"{rut}-{dig}"; + } + + return $"{num}-{dig}"; + } + + /// + /// Algorithm to generate a verification digit based on an integer between 1000000 and 99999999 + /// + /// Represents a full valid RUT number + /// A string representing a number that validates the provided number + private static string Digito(int rut) + { + if (rut < 1000000 || rut > 99999999) + throw new ArgumentOutOfRangeException($"The provided integer is outside of the range between 1000000 and 99999999"); + + int suma = 0; + int multiplicador = 1; + + while (rut != 0) + { + multiplicador++; + if (multiplicador == 8) + multiplicador = 2; + suma += (rut % 10) * multiplicador; + rut /= 10; + } + + suma = 11 - (suma % 11); + + if (suma == 11) + { + return "0"; + } + else if (suma == 10) + { + return "K"; + } + else + { + return suma.ToString(); + } + } + } +} +