Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new Chilean RUT generator #487

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
103 changes: 103 additions & 0 deletions Source/Bogus.Tests/ExtensionTests/ChileanRutExtensionTest.cs
Original file line number Diff line number Diff line change
@@ -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<Person>()
.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<Person>()
.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();
}
}
}
}
92 changes: 92 additions & 0 deletions Source/Bogus/Extensions/Chile/ExtensionsForChile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using Bogus.DataSets;

namespace Bogus.Extensions.Chile
{
/// <summary>
/// API extensions specific for a geographical location.
/// </summary>
public static class ExtensionsForChile
{
/// <summary>
/// Generates a valid Chilean RUT for a Person (Rol Unico Tributario)
/// </summary>
/// <param name="dotFormat">Use the thousands separator for the Chilean RUT (11.111.111-1)</param>
/// <returns>A string representation for a valid Chilean RUT (Rol Unico Tributario)</returns>
public static string Rut(this Person person, bool dotFormat = false)
{
return GenerateChileanId(dotFormat);
}

/// <summary>
/// Generates a valid Chilean RUT for a Company (Rol Unico Tributario)
/// </summary>
/// <param name="dotFormat">Use the thousands separator for the Chilean RUT (11.111.111-1)</param>
/// <returns>A string representation for a valid Chilean RUT (Rol Unico Tributario)</returns>

public static string Rut(this Company company, bool dotFormat = true)
{
return GenerateChileanId(dotFormat);
}

/// <summary>
/// A general Chilean ID generator
/// </summary>
/// <param name="dotFormat">Use the thousands separator for the Chilean RUT (11.111.111-1)</param>
/// <returns></returns>
private static string GenerateChileanId(bool dotFormat = true)
{
Random rnd = new();
int num = rnd.Next(1000000, 99999999);
Comment on lines +39 to +40
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't call new Random() in Bogus because it's not deterministic. We'll need to source the rnd from Person.Random to get the randomizer, and then ask for the rnd.Next().


string dig = Digito(num);

if (dotFormat)
{
var rut = string.Format("{0:0,0}", num);
return $"{rut}-{dig}";
}

return $"{num}-{dig}";
}

/// <summary>
/// Algorithm to generate a verification digit based on an integer between 1000000 and 99999999
/// </summary>
/// <param name="rut">Represents a full valid RUT number</param>
/// <returns>A string representing a number that validates the provided number</returns>
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();
}
}
}
}