Skip to content
Open
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
Copy Markdown
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();
}
}
}
}