├── appveyor.yml
├── logo.png
├── tools
└── NuGet
│ └── nuget.exe
├── .gitignore
├── src
├── RfcFacil
│ ├── packages
│ │ ├── RfcFacil.1.0.0.nupkg
│ │ ├── RfcFacil.1.0.1.nupkg
│ │ └── RfcFacil.1.0.2.nupkg
│ ├── IHomoclavePerson.cs
│ ├── Person.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── JuristicPersonTenDigitsCodeCalculator.cs
│ ├── JuristicPerson.cs
│ ├── RfcUtils.cs
│ ├── RfcFacil.nuspec
│ ├── NaturalPerson.cs
│ ├── Rfc.cs
│ ├── VerificationDigitCalculator.cs
│ ├── RfcFacil.csproj
│ ├── RfcBuilder.cs
│ ├── HomoclaveCalculator.cs
│ └── NaturalPersonTenDigitsCodeCalculator.cs
├── RfcFacil.SampleConsole
│ ├── App.config
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── RfcFacil.SampleConsole.csproj
└── RfcFacil.sln
├── README.md
└── LICENSE
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 1.0.{build}
2 | build:
3 | verbosity: minimal
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/migsalazar/RfcFacil/HEAD/logo.png
--------------------------------------------------------------------------------
/tools/NuGet/nuget.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/migsalazar/RfcFacil/HEAD/tools/NuGet/nuget.exe
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | release/
3 | bin
4 | Bin
5 | obj
6 | *.suo
7 | *.user
8 | *.csproj.user
9 | .vs
10 | .nuget
--------------------------------------------------------------------------------
/src/RfcFacil/packages/RfcFacil.1.0.0.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/migsalazar/RfcFacil/HEAD/src/RfcFacil/packages/RfcFacil.1.0.0.nupkg
--------------------------------------------------------------------------------
/src/RfcFacil/packages/RfcFacil.1.0.1.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/migsalazar/RfcFacil/HEAD/src/RfcFacil/packages/RfcFacil.1.0.1.nupkg
--------------------------------------------------------------------------------
/src/RfcFacil/packages/RfcFacil.1.0.2.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/migsalazar/RfcFacil/HEAD/src/RfcFacil/packages/RfcFacil.1.0.2.nupkg
--------------------------------------------------------------------------------
/src/RfcFacil/IHomoclavePerson.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace RfcFacil
3 | {
4 | internal interface IHomoclavePerson
5 | {
6 | string GetFullNameForHomoclave();
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/RfcFacil.SampleConsole/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/RfcFacil/Person.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace RfcFacil
3 | {
4 | internal class Person
5 | {
6 | public string Name { get; set; }
7 | public int Year { get; set; }
8 | public int Month { get; set; }
9 | public int Day { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/RfcFacil/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | [assembly: AssemblyTitle("RfcFacil")]
4 | [assembly: AssemblyDescription("Librería para el cálculo del RFC del SAT en México")]
5 | [assembly: AssemblyCompany("Miguel Salazar")]
6 | [assembly: AssemblyProduct("RfcFacil.NET")]
7 | [assembly: AssemblyVersion("1.0.0.0")]
8 | [assembly: AssemblyFileVersion("1.0.0.0")]
9 |
--------------------------------------------------------------------------------
/src/RfcFacil.SampleConsole/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RfcFacil.SampleConsole
4 | {
5 | class Program
6 | {
7 | static void Main(string[] args)
8 | {
9 | var rfc = RfcBuilder.ForNaturalPerson()
10 | .WithName("Miguel Angel")
11 | .WithFirstLastName("Salazar")
12 | .WithSecondLastName("Santillán")
13 | .WithDate(1987, 4, 15)
14 | .Build();
15 |
16 | Console.WriteLine(rfc);
17 |
18 | Console.ReadKey();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/RfcFacil/JuristicPersonTenDigitsCodeCalculator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RfcFacil
4 | {
5 | internal class JuristicPersonTenDigitsCodeCalculator
6 | {
7 | private JuristicPerson person;
8 |
9 | public JuristicPersonTenDigitsCodeCalculator(JuristicPerson person)
10 | {
11 | // TODO: Complete member initialization
12 | this.person = person;
13 | }
14 |
15 | ///
16 | /// TODO
17 | ///
18 | ///
19 | internal string Calculate()
20 | {
21 | throw new NotImplementedException();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/RfcFacil/JuristicPerson.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace RfcFacil
3 | {
4 | internal class JuristicPerson
5 | {
6 | private string Name;
7 | private int Day;
8 | private int Month;
9 | private int Year;
10 |
11 | ///
12 | /// TODO
13 | ///
14 | ///
15 | ///
16 | ///
17 | ///
18 | public JuristicPerson(string Name, int Day, int Month, int Year)
19 | {
20 | // TODO: Complete member initialization
21 | this.Name = Name;
22 | this.Day = Day;
23 | this.Month = Month;
24 | this.Year = Year;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/RfcFacil/RfcUtils.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Linq;
3 | using System.Text;
4 |
5 | namespace RfcFacil
6 | {
7 | internal static class RfcUtils
8 | {
9 | ///
10 | /// Remove diacritics, ex:
11 | // "ÁÂÃÄÅÇÈÉàáâãäåèéêëìíîïòóôõ" ====>> "AAAAACEEaaaaaaeeeeiiiioooo"
12 | ///
13 | /// target word
14 | /// result word
15 | public static string StripAccents(string word)
16 | {
17 | string normal = word.Normalize(NormalizationForm.FormD);
18 |
19 | var converted = normal.Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark);
20 |
21 | return new string(converted.ToArray());
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/RfcFacil/RfcFacil.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | 1.0.2
6 | RfcFacil .NET
7 | Mig Salazar
8 | Mig Salazar
9 | https://github.com/migsalazar/RfcFacil/blob/master/LICENSE
10 | http://migsalazar.github.io/RfcFacil
11 | https://raw.githubusercontent.com/migsalazar/RfcFacil/master/logo.png
12 | false
13 | Liberaría para el cálculo del RFC (Registro Federal de Contribuyentes) en .NET
14 | Add internal instead public
15 |
16 | RFC SAT .NET
17 |
18 |
--------------------------------------------------------------------------------
/src/RfcFacil/NaturalPerson.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace RfcFacil
3 | {
4 | internal class NaturalPerson : Person, IHomoclavePerson
5 | {
6 | public string FirstLastName { get; set; }
7 | public string SecondLastName { get; set; }
8 |
9 | ///
10 | ///
11 | ///
12 | ///
13 | ///
14 | ///
15 | ///
16 | ///
17 | ///
18 | public NaturalPerson(string name, string firstLastName, string secondLastName, int year, int month, int day)
19 | {
20 | this.Name = name;
21 | this.FirstLastName = firstLastName;
22 | this.SecondLastName = secondLastName;
23 | this.Year = year;
24 | this.Month = month;
25 | this.Day = day;
26 | }
27 |
28 | ///
29 | ///
30 | ///
31 | ///
32 | public string GetFullNameForHomoclave()
33 | {
34 | return string.Format("{0} {1} {2}", this.FirstLastName, this.SecondLastName, this.Name);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/RfcFacil/Rfc.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace RfcFacil
3 | {
4 | public class Rfc
5 | {
6 | public string TenDigitsCode { get; private set; }
7 | public string Homoclave { get; private set; }
8 | public string VerificationDigit { get; private set; }
9 |
10 | ///
11 | ///
12 | ///
13 | ///
14 | ///
15 | ///
16 | private Rfc(string tenDigitsCode, string homoclave, string verificationDigit)
17 | {
18 | this.TenDigitsCode = tenDigitsCode;
19 | this.Homoclave = homoclave;
20 | this.VerificationDigit = verificationDigit;
21 | }
22 |
23 | ///
24 | ///
25 | ///
26 | ///
27 | ///
28 | ///
29 | ///
30 | public static Rfc Build(string tenDigitsCode, string homoclave, string verificationDigit)
31 | {
32 | return new Rfc(tenDigitsCode, homoclave, verificationDigit);
33 | }
34 |
35 | ///
36 | ///
37 | ///
38 | ///
39 | public override string ToString()
40 | {
41 | return this.TenDigitsCode + this.Homoclave + this.VerificationDigit;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/RfcFacil.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.40629.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RfcFacil", "RfcFacil\RfcFacil.csproj", "{67C4B9AB-12C1-4ADD-8841-09233EBDEB99}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RfcFacil.SampleConsole", "RfcFacil.SampleConsole\RfcFacil.SampleConsole.csproj", "{431B7D75-B177-43CB-905A-AC1ADE02A8C5}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {67C4B9AB-12C1-4ADD-8841-09233EBDEB99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {67C4B9AB-12C1-4ADD-8841-09233EBDEB99}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {67C4B9AB-12C1-4ADD-8841-09233EBDEB99}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {67C4B9AB-12C1-4ADD-8841-09233EBDEB99}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {431B7D75-B177-43CB-905A-AC1ADE02A8C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {431B7D75-B177-43CB-905A-AC1ADE02A8C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {431B7D75-B177-43CB-905A-AC1ADE02A8C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {431B7D75-B177-43CB-905A-AC1ADE02A8C5}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/src/RfcFacil.SampleConsole/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RfcFacil.SampleConsole")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Miguel Salazar")]
12 | [assembly: AssemblyProduct("RfcFacil.SampleConsole")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("db3d63c7-1c98-4672-b40d-bc4be0717eb0")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/RfcFacil/VerificationDigitCalculator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace RfcFacil
5 | {
6 | internal class VerificationDigitCalculator
7 | {
8 | private readonly string Rfc12Digits;
9 | private static readonly Dictionary Mapping = new Dictionary()
10 | {
11 | {"0", 0},
12 | {"1", 1},
13 | {"2", 2},
14 | {"3", 3},
15 | {"4", 4},
16 | {"5", 5},
17 | {"6", 6},
18 | {"7", 7},
19 | {"8", 8},
20 | {"9", 9},
21 | {"A", 10},
22 | {"B", 11},
23 | {"C", 12},
24 | {"D", 13},
25 | {"E", 14},
26 | {"F", 15},
27 | {"G", 16},
28 | {"H", 17},
29 | {"I", 18},
30 | {"J", 19},
31 | {"K", 20},
32 | {"L", 21},
33 | {"M", 22},
34 | {"N", 23},
35 | {"&", 24},
36 | {"O", 25},
37 | {"P", 26},
38 | {"Q", 27},
39 | {"R", 28},
40 | {"S", 29},
41 | {"T", 30},
42 | {"U", 31},
43 | {"V", 32},
44 | {"W", 33},
45 | {"X", 34},
46 | {"Y", 35},
47 | {"Z", 36},
48 | {" ", 37},
49 | {"Ñ", 38}
50 | };
51 |
52 | ///
53 | ///
54 | ///
55 | ///
56 | public VerificationDigitCalculator(string rfc12Digits)
57 | {
58 | this.Rfc12Digits = rfc12Digits.PadLeft(12);
59 | }
60 |
61 | ///
62 | ///
63 | ///
64 | ///
65 | public string Calculate()
66 | {
67 | int sum = 0;
68 | int reminder;
69 |
70 | for (int i = 0; i < 12; i++)
71 | {
72 | sum += MapDigit(this.Rfc12Digits[i]) * (13 - i);
73 | }
74 |
75 | reminder = sum % 11;
76 |
77 | if (reminder == 0)
78 | {
79 | return "0";
80 | }
81 | else
82 | {
83 | return (11 - reminder).ToString("X");
84 | }
85 | }
86 |
87 | private int MapDigit(char c)
88 | {
89 | int outValue = 0; //redundance
90 |
91 | bool hasOutput = Mapping.TryGetValue(c.ToString(), out outValue);
92 |
93 | return hasOutput ? outValue : 0;
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/RfcFacil.SampleConsole/RfcFacil.SampleConsole.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {431B7D75-B177-43CB-905A-AC1ADE02A8C5}
8 | Exe
9 | Properties
10 | RfcFacil.SampleConsole
11 | RfcFacil.SampleConsole
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | {67c4b9ab-12c1-4add-8841-09233ebdeb99}
53 | RfcFacil
54 |
55 |
56 |
57 |
64 |
--------------------------------------------------------------------------------
/src/RfcFacil/RfcFacil.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {67C4B9AB-12C1-4ADD-8841-09233EBDEB99}
8 | Library
9 | Properties
10 | RfcFacil
11 | RfcFacil
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | Librería para el cálculo del RFC (Registro Federal de Contribuyentes) del SAT (Servicio de Administración Tributaria) en .NET
4 |
5 | [](https://ci.appveyor.com/project/migsalazar/rfcfacil/branch/master)
6 |
7 | ## Uso
8 |
9 | 1.- Instala RfcFacil en tu proyecto [vía NuGet](https://www.nuget.org/packages/RfcFacil/):
10 |
11 | ```
12 | PM> Install-Package RfcFacil
13 | ```
14 |
15 | 2.- Calcular el RFC es muy sencillo:
16 |
17 | - Personas físicas
18 |
19 | C#
20 | ```csharp
21 | using RfcFacil;
22 | namespace ConsoleApplication {
23 | class Program {
24 | static void Main(string[] args) {
25 | var rfc = RfcBuilder.ForNaturalPerson()
26 | .WithName("Miguel Angel")
27 | .WithFirstLastName("Salazar")
28 | .WithSecondLastName("Santillan")
29 | .WithDate(1987, 04, 15)
30 | .Build();
31 |
32 | Console.WriteLine(rfc.ToString());
33 | }
34 | }
35 | }
36 | ```
37 | VB
38 | ```vb
39 | Imports RfcFacil
40 | Module Module1
41 | Sub Main()
42 | Dim rfc = RfcBuilder.ForNaturalPerson() _
43 | .WithName("Miguel Angel") _
44 | .WithFirstLastName("Salazar") _
45 | .WithSecondLastName("Santillan") _
46 | .WithDate(1987, 4, 15)
47 |
48 | Console.Write(rfc)
49 | End Sub
50 | End Module
51 | ```
52 |
53 | - Personas morales
54 |
55 | ```csharp
56 | //coming soon :B
57 | ```
58 |
59 | ## Fuente
60 | Esta librería se basa en documentación oficial obtenida por medio del IFAI (Instituto Federal de Acceso a la Información). El documento puede ser consultado en el sitio de [INFOMEX](https://www.infomex.org.mx/gobiernofederal/moduloPublico/moduloPublico.action) con el folio `0610100135506`.
61 |
62 | Cabe advertir que sólo la Secretaría de Hacienda y Crédito Público, a través del Servicio de Administración Tributaria, es la única instancia que oficialmente asigna las claves de RFC a los contribuyentes que así lo soliciten, a partir de la aplicación de este procedimiento a la base de datos del Padrón de Contribuyentes, con la finalidad de identificar homonimias y evitar la duplicidad de registros.
63 |
64 | ## En otros lenguajes
65 | - JAVA [josketres/rfc-facil](https://github.com/josketres/rfc-facil)
66 | - Ruby [acrogenesis/rfc_facil](https://github.com/acrogenesis/rfc_facil)
67 |
68 | ## Contribuciones
69 | - Reporta errores o sugerencias en: [https://github.com/migsalazar/RfcFacil/issues](https://github.com/migsalazar/RfcFacil/issues)
70 |
71 | ## Agradecimientos
72 | RfcFacil .NET es una versión para .NET de la librería [rfc-facil](http://josketres.github.io/rfc-facil/) escrita por [josketres](https://github.com/josketres). Gracias!
73 |
74 | ## Licencia
75 | Licensed under the Apache License, Version 2.0.
76 |
--------------------------------------------------------------------------------
/src/RfcFacil/RfcBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RfcFacil
4 | {
5 | public class RfcBuilder
6 | {
7 | private string Name;
8 | private string FirstLastName;
9 | private string SecondLastName;
10 | private int Year;
11 | private int Month;
12 | private int Day;
13 |
14 | private bool IsNaturalPerson;
15 |
16 | ///
17 | /// Constructor
18 | ///
19 | /// Set if person is Natural or Juristic
20 | private RfcBuilder(bool isNaturalPerson)
21 | {
22 | this.IsNaturalPerson = isNaturalPerson;
23 | }
24 |
25 | ///
26 | /// Init path
27 | ///
28 | /// Instance of Rfc
29 | public Rfc Build()
30 | {
31 | return this.IsNaturalPerson ? BuildForNaturalPerson() : BuildForJuristicPerson();
32 | }
33 |
34 | ///
35 | /// Build Natural Person - Main logic
36 | ///
37 | /// instance of RFC (wrapped by static method Rfc.Build)
38 | private Rfc BuildForNaturalPerson()
39 | {
40 | NaturalPerson person = new NaturalPerson(this.Name, this.FirstLastName, this.SecondLastName, this.Year, this.Month, this.Day);
41 |
42 | string tenDigitsCode = new NaturalPersonTenDigitsCodeCalculator(person).Calculate();
43 | string homoclave = new HomoclaveCalculator(person).Calculate();
44 | string verificationDigit = new VerificationDigitCalculator(tenDigitsCode + homoclave).Calculate();
45 |
46 | return Rfc.Build(tenDigitsCode, homoclave, verificationDigit);
47 | }
48 |
49 | ///
50 | /// Build Juristic Person - Main logic
51 | ///
52 | /// instance of RFC (wrapped by static method Rfc.Build)
53 | private Rfc BuildForJuristicPerson()
54 | {
55 | throw new NotImplementedException();
56 | }
57 |
58 | ///
59 | /// Set person type
60 | ///
61 | ///
62 | public static RfcBuilder ForNaturalPerson()
63 | {
64 | return new RfcBuilder(true);
65 | }
66 |
67 | ///
68 | /// Set person type
69 | ///
70 | ///
71 | public static RfcBuilder ForJuristicPerson()
72 | {
73 | return new RfcBuilder(false);
74 | }
75 |
76 | ///
77 | /// Set Name (Legal Name or Person Name)
78 | ///
79 | /// Instance of RfcBuilder to be fluent
80 | public RfcBuilder WithName(string name)
81 | {
82 | this.Name = name;
83 | return this;
84 | }
85 |
86 | ///
87 | /// Set FirsLastName
88 | ///
89 | ///
90 | ///
91 | public RfcBuilder WithFirstLastName(string firstLastName)
92 | {
93 | if (!this.IsNaturalPerson)
94 | {
95 | throw new MethodAccessException("WithFirstLastName method can't be used with ForJuristicPerson method");
96 | }
97 |
98 | this.FirstLastName = firstLastName;
99 | return this;
100 | }
101 |
102 | ///
103 | /// Set SecondLastName
104 | ///
105 | ///
106 | ///
107 | public RfcBuilder WithSecondLastName(string secondLastName)
108 | {
109 | if (!this.IsNaturalPerson)
110 | {
111 | throw new MethodAccessException("WithSecondLastName method can't be used with ForJuristicPerson method");
112 | }
113 |
114 | this.SecondLastName = secondLastName;
115 | return this;
116 | }
117 |
118 | ///
119 | /// Set birthdate/creation date
120 | ///
121 | ///
122 | ///
123 | ///
124 | ///
125 | public RfcBuilder WithDate(int year, int month, int day)
126 | {
127 | this.Year = year;
128 | this.Month = month;
129 | this.Day = day;
130 |
131 | return this;
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/RfcFacil/HomoclaveCalculator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace RfcFacil
6 | {
7 | internal class HomoclaveCalculator
8 | {
9 | private static IHomoclavePerson IHomoclavePerson;
10 | private string FullName;
11 | private string MappedFullName;
12 | private long PairsOfDigitsSum;
13 | private string Homoclave;
14 | private static readonly string HomoclaveDigits = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
15 | private static readonly Dictionary FullNameMapping = new Dictionary()
16 | {
17 | {" ", "00"},
18 | {"0", "00"},
19 | {"1", "01"},
20 | {"2", "02"},
21 | {"3", "03"},
22 | {"4", "04"},
23 | {"5", "05"},
24 | {"6", "06"},
25 | {"7", "07"},
26 | {"8", "08"},
27 | {"9", "09"},
28 | {"&", "10"},
29 | {"A", "11"},
30 | {"B", "12"},
31 | {"C", "13"},
32 | {"D", "14"},
33 | {"E", "15"},
34 | {"F", "16"},
35 | {"G", "17"},
36 | {"H", "18"},
37 | {"I", "19"},
38 | {"J", "21"},
39 | {"K", "22"},
40 | {"L", "23"},
41 | {"M", "24"},
42 | {"N", "25"},
43 | {"O", "26"},
44 | {"P", "27"},
45 | {"Q", "28"},
46 | {"R", "29"},
47 | {"S", "32"},
48 | {"T", "33"},
49 | {"U", "34"},
50 | {"V", "35"},
51 | {"W", "36"},
52 | {"X", "37"},
53 | {"Y", "38"},
54 | {"Z", "39"},
55 | {"Ñ", "40"}
56 | };
57 |
58 | public HomoclaveCalculator(IHomoclavePerson person) {
59 |
60 | IHomoclavePerson = person;
61 | }
62 |
63 | public string Calculate() {
64 |
65 | NormalizeFullName();
66 | MapFullNameToDigitsCode();
67 | SumPairsOfDigits();
68 | BuildHomoclave();
69 |
70 | return Homoclave;
71 | }
72 |
73 | private void BuildHomoclave() {
74 |
75 | int lastThreeDigits = (int) PairsOfDigitsSum % 1000;
76 | int quo = lastThreeDigits / 34;
77 | int reminder = lastThreeDigits % 34;
78 |
79 | Homoclave = HomoclaveDigits[quo].ToString() + HomoclaveDigits[reminder].ToString();
80 | }
81 |
82 | private void SumPairsOfDigits() {
83 |
84 | PairsOfDigitsSum = 0;
85 |
86 | for (int i = 0; i < MappedFullName.Length - 1; i++) {
87 |
88 | long intNum1 = long.Parse(MappedFullName.Substring(i, 2));
89 |
90 | long intNum2 = long.Parse(MappedFullName.Substring(i + 1, 1));
91 |
92 | PairsOfDigitsSum += intNum1 * intNum2;
93 | }
94 | }
95 |
96 | private void MapFullNameToDigitsCode() {
97 |
98 | MappedFullName = "0";
99 |
100 | for (int i = 0; i < FullName.Length; i++) {
101 | MappedFullName += MapCharacterToTwoDigitCode(FullName[i].ToString());
102 | }
103 | }
104 |
105 | private string MapCharacterToTwoDigitCode(string c) {
106 |
107 | string outValue = "";
108 |
109 | if (!FullNameMapping.TryGetValue(c, out outValue)) {
110 | throw new ArgumentException("No two-digit-code mapping for char: " + c);
111 | }
112 |
113 | return outValue;
114 | }
115 |
116 | private void NormalizeFullName() {
117 |
118 | string rawFullName = IHomoclavePerson.GetFullNameForHomoclave().ToUpper();
119 |
120 | FullName = RfcUtils.StripAccents(rawFullName);
121 | FullName = FullName.Replace("[\\-\\.',]", "");
122 | FullName = AddMissingCharToFullName(rawFullName, 'Ñ');
123 |
124 | }
125 |
126 | private string AddMissingCharToFullName(string rawFullName, char missingChar) {
127 |
128 | StringBuilder newFullName;
129 | int index = rawFullName.IndexOf(missingChar);
130 |
131 | if (index == -1) {
132 | return FullName;
133 | }
134 |
135 | newFullName = new StringBuilder(FullName);
136 |
137 | while (index >= 0) {
138 | newFullName[index] = missingChar;
139 | index = rawFullName.IndexOf(missingChar, index + 1);
140 | }
141 |
142 | return newFullName.ToString();
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/src/RfcFacil/NaturalPersonTenDigitsCodeCalculator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace RfcFacil
6 | {
7 | internal class NaturalPersonTenDigitsCodeCalculator
8 | {
9 | private NaturalPerson person;
10 |
11 | private static readonly string VowelPattern = "[AEIOU]+";
12 |
13 | private static readonly string[] SpecialParticles = {
14 | "DE", "LA", "LAS", "MC", "VON", "DEL", "LOS", "Y", "MAC", "VAN", "MI"};
15 |
16 | private static readonly string[] ForbiddenWords = {
17 | "BUEI", "BUEY", "CACA", "CACO", "CAGA", "KOGE", "KAKA", "MAME", "KOJO", "KULO",
18 | "CAGO", "COGE", "COJE", "COJO", "FETO", "JOTO", "KACO", "KAGO", "MAMO", "MEAR", "MEON",
19 | "MION", "MOCO", "MULA", "PEDA", "PEDO", "PENE", "PUTA", "PUTO", "QULO", "RATA", "RUIN"
20 | };
21 |
22 | ///
23 | ///
24 | ///
25 | ///
26 | public NaturalPersonTenDigitsCodeCalculator(NaturalPerson person)
27 | {
28 | this.person = person;
29 | }
30 |
31 | ///
32 | ///
33 | ///
34 | ///
35 | public string Calculate()
36 | {
37 | return ObfuscateForbiddenWords(NameCode()) + BirthdayCode();
38 | }
39 |
40 | ///
41 | ///
42 | ///
43 | ///
44 | ///
45 | private string ObfuscateForbiddenWords(string nameCode)
46 | {
47 | foreach(var forbidden in ForbiddenWords)
48 | {
49 | if (forbidden.Equals(nameCode))
50 | {
51 | return string.Format("{0}{1}", nameCode.Substring(0, 3), "X");
52 | }
53 | }
54 |
55 | return nameCode;
56 | }
57 |
58 | ///
59 | ///
60 | ///
61 | ///
62 | private string NameCode()
63 | {
64 | if (IsFirstLastNameEmpty())
65 | {
66 | return FirstLastNameEmptyForm();
67 | }
68 | else
69 | {
70 | if (IsSecondLastNameEmpty())
71 | {
72 | return SecondLastNameEmptyForm();
73 | }
74 | else
75 | {
76 | if (IsFirstLastNameIsTooShort())
77 | {
78 | return FirstLastNameTooShortForm();
79 | }
80 | else
81 | {
82 | return NormalForm();
83 | }
84 | }
85 | }
86 | }
87 |
88 | ///
89 | ///
90 | ///
91 | ///
92 | private string BirthdayCode()
93 | {
94 | DateTime birthday = new DateTime(person.Year, person.Month, person.Day);
95 |
96 | return birthday.ToString("yyMMdd");
97 | }
98 |
99 | ///
100 | ///
101 | ///
102 | ///
103 | private bool IsFirstLastNameEmpty()
104 | {
105 | return string.IsNullOrEmpty(Normalize(person.FirstLastName));
106 | }
107 |
108 | ///
109 | ///
110 | ///
111 | ///
112 | private bool IsSecondLastNameEmpty()
113 | {
114 | return string.IsNullOrEmpty(Normalize(person.SecondLastName));
115 | }
116 |
117 | ///
118 | ///
119 | ///
120 | ///
121 | private string FirstLastNameEmptyForm()
122 | {
123 | return
124 | FirstTwoLettersOf(person.SecondLastName) +
125 | FirstTwoLettersOf(FilterName(person.Name));
126 | }
127 |
128 | ///
129 | ///
130 | ///
131 | ///
132 | private string SecondLastNameEmptyForm()
133 | {
134 | return
135 | FirstTwoLettersOf(person.FirstLastName) +
136 | FirstTwoLettersOf(FilterName(person.Name));
137 | }
138 |
139 | ///
140 | ///
141 | ///
142 | ///
143 | private bool IsFirstLastNameIsTooShort()
144 | {
145 | return Normalize(person.FirstLastName).Length <= 2;
146 | }
147 |
148 | ///
149 | ///
150 | ///
151 | ///
152 | private string FirstLastNameTooShortForm()
153 | {
154 | return
155 | FirstLetterOf(person.FirstLastName) +
156 | FirstLetterOf(person.SecondLastName) +
157 | FirstTwoLettersOf(FilterName(person.Name));
158 | }
159 |
160 | ///
161 | ///
162 | ///
163 | ///
164 | private string NormalForm()
165 | {
166 | return
167 | FirstLetterOf(person.FirstLastName) +
168 | FirstVowelExcludingFirstCharacterOf(person.FirstLastName) +
169 | FirstLetterOf(person.SecondLastName) +
170 | FirstLetterOf(FilterName(person.Name));
171 | }
172 |
173 | ///
174 | ///
175 | ///
176 | ///
177 | ///
178 | private string FirstVowelExcludingFirstCharacterOf(string word)
179 | {
180 | string normalizedWord = Normalize(word).Substring(1);
181 |
182 | Match m = Regex.Match(normalizedWord, VowelPattern);
183 |
184 | if (m.Length <= 0)
185 | {
186 | throw new ArgumentException("Word doesn't contain a vowel: " + normalizedWord);
187 | }
188 |
189 | return normalizedWord[m.Index].ToString();
190 | }
191 |
192 | ///
193 | ///
194 | ///
195 | ///
196 | ///
197 | private string FirstTwoLettersOf(string word)
198 | {
199 | string normalizedWord = Normalize(word);
200 |
201 | return normalizedWord.Substring(0, 2);
202 | }
203 |
204 | ///
205 | ///
206 | ///
207 | ///
208 | ///
209 | private string FilterName(string name)
210 | {
211 | bool isPopularGivenName = false;
212 | string rawName = Normalize(name).Trim();
213 |
214 | if (rawName.Contains(" "))
215 | {
216 | isPopularGivenName = rawName.StartsWith("MARIA") || rawName.StartsWith("JOSE");
217 |
218 | if (isPopularGivenName)
219 | {
220 | return rawName.Split(' ')[1];
221 | }
222 | }
223 | return name;
224 | }
225 |
226 | ///
227 | ///
228 | ///
229 | ///
230 | ///
231 | private string FirstLetterOf(string word)
232 | {
233 | string normalizedWord = Normalize(word);
234 |
235 | return normalizedWord[0].ToString();
236 | }
237 |
238 | ///
239 | ///
240 | ///
241 | ///
242 | ///
243 | private string Normalize(string word)
244 | {
245 | if (string.IsNullOrEmpty(word))
246 | {
247 | return word;
248 | }
249 | else
250 | {
251 | string normalizedWord = RfcUtils.StripAccents(word).ToUpper();
252 | return RemoveSpecialParticles(normalizedWord, SpecialParticles);
253 | }
254 | }
255 |
256 | ///
257 | ///
258 | ///
259 | ///
260 | ///
261 | ///
262 | private string RemoveSpecialParticles(string normalizedWord, string[] SpecialParticles)
263 | {
264 | StringBuilder newWord = new StringBuilder(normalizedWord);
265 |
266 | foreach(var particle in SpecialParticles)
267 | {
268 | var particlePositions = new [] { particle + " ", " " + particle };
269 |
270 | foreach(var p in particlePositions)
271 | {
272 | while (newWord.ToString().Contains(p)) {
273 | int i = newWord.ToString().IndexOf(p);
274 | newWord.Remove(i, i + p.ToString().Length);
275 | }
276 | }
277 | }
278 |
279 | return newWord.ToString();
280 | }
281 | }
282 | }
283 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2016 Miguel Angel Salazar Santillán
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------