arthurdejong / python-stdnum

A Python library to provide functions to handle, parse and validate standard numbers.
https://arthurdejong.org/python-stdnum/
GNU Lesser General Public License v2.1
495 stars 205 forks source link

Bug in validate RUC #267

Closed vixrodriguez closed 2 years ago

vixrodriguez commented 3 years ago

The method validate has 2 wrong check:

1) Validation of Natural RUC

image

The 3rd element in the number can be 6, because the Natural RUC is created from CI.

Example

Natural RUC valid: 0962467429001

image

Check RUC in government page: https://srienlinea.sri.gob.ec/sri-en-linea/SriRucWeb/ConsultaRuc/Consultas/consultaRuc

CI valid: 0962467429

image

Check CI in goverment page: https://servicios.registrocivil.gob.ec/cdd/

2) Checksum array

The coefficients in the checksum array have an additional coefficient that should not be considered.

Ref: https://rucecuador.net/que-es-el-ruc/

image Path file: stdnum/ec/ruc.py

Correct coefficients for public RUC: [3, 2, 7, 6, 5, 4, 3, 2]

Correct coefficients for juridical RUC: [4, 3, 2, 7, 6, 5, 4, 3, 2]

image

For example

Public RUC valid: 0968599020001

Digit Coefficient Result
0 3 0
9 2 18
6 7 42
8 6 48
5 5 25
9 4 36
9 3 27
0 2 0
Total 196

Mod: 196 % 11 = 9 Digit verificator = 11 - mod = 11 - 9 = 2

And exceptional case, if mod == 0, then Digit verificator = 0.

9th element of Public RUC valid = 2

Digit verificator == 9th element of RUC? True ==> Valid RUC False ==> Not valid RUC

arthurdejong commented 2 years ago

Hi @vixrodriguez,

Thanks for pointing this out and my apologies that it took so long to respond.

Regarding the incorrect detection of the natural RUC:

The current implementation uses the third digit of the RUC to determine whether it is a natural RUC, a public RUC or a juridical RUC however it seems that if the third digit is a 6 it can be either a natural RUC or a public RUC. Do you know if there is any way to distinguish the two situations without calculating both checksums? I've fixed this in 1a0e613 that checks whether a RUC where the third digit is either a CI plus establishment number or a public RUC.

Regarding the checksum calculation:

Setting the weight of the last digit (the check digit) to 1 and calculating the weighted sum (module 11) is exactly the same as calculating the weighted sum over all but the check digit and doing 11 - the sum. The number you provided (0968599020001) is also considered valid according to the current implementation.

For example, for 0968599020001:

Digit Weight Result Weight Result
0 3 0 3 0
9 2 18 2 18
6 7 42 7 42
8 6 48 6 48
5 5 25 5 25
9 4 36 4 36
9 3 27 3 27
0 2 0 2 0
2 - - 1 2
sum = 196 sum = 198
sum % 11 = 9 sum % 11 = 0
11 - 9 = 2 OK: result = 0
OK: digits match

The exception mentioned when the sum is 0 is not really an exception. For example, for the fictional number 186975960:

Digit Weight Result Weight Result
1 3 3 3 3
8 2 16 2 16
6 7 42 7 42
9 6 54 6 54
7 5 35 5 35
5 4 20 4 20
9 3 27 3 27
6 2 12 2 12
0 - - 1 0
sum = 209 sum = 209
sum % 11 = 0 sum % 11 = 0
exception: 0 OK: result = 0
OK: digits match

It would be different if an exception was also specified for when the sum would be 1. With the algorithm documented on https://rucecuador.net/que-es-el-ruc/ that would result in a check digit of "10" which is not a single digit and would assumably indicate an invalid number.

Thanks for providing the clear examples and references.