如何计算巴拉圭国家税务ID的验证数字(calcular digito verificador del RUC)



在巴拉圭(南美洲(,每个纳税人都有一个由政府(Ministerio de Hacienda,Secretaría de Tributación(分配的税务ID(称为RUC:RegisteroÚnico del Contribuyente(。

该RUC是一个后面跟着验证数字(dígito-verificador(的数字,例如123456-0。当你申请RUC时,政府会告诉你验证数字。

有没有一种方法可以让我根据RUC计算验证数字?这是一个已知的公式吗?

就我而言,我有一个供应商和客户的数据库,这些数据库是公司几名员工多年来收集的。现在我需要进行检查,看看是否所有的RUC都输入正确,或者是否有打字错误。

我更喜欢Python解决方案,但我会采取任何解决方案,为我指明正确的方向。


编辑:这是一个分享我花了数小时/数天时间才找到的知识的自我回答。我把这个问题标记为"回答你自己的问题"(不知道这是否会改变什么(。

RUC的验证数字是使用与Modulo 11方法非常相似(但不相等(的公式计算的;这至少是我在阅读以下科技网站时得到的信息(内容是西班牙语(:

  • https://www.yoelprogramador.com/funncion-para-calcular-el-digito-verificador-del-ruc/
  • http://groovypy.wikidot.com/blog:02
  • https://es.wikipedia.org/wiki/C%C3%B3digo_de_control#M.C3.B3dulo_11

我分析了上述页面中提供的解决方案,并根据RUC及其已知验证数字的列表进行了自己的测试,这使我得出了一个最终公式,该公式返回了预期输出,但与上述链接中的解决方案不同。

2023年3月更新:这是SET(政府机构(的官方文件https://www.set.gov.py/portal/PARAGUAY-SET/detail?content-id=/repository/collection/sites/PARAGUAY-SET/documents/heramentas/digito-verificador.pdf


我得到的计算RUC验证数字的最终公式如本例所示(80009735-1(:

  1. 将RUC的每个数字(不考虑验证数字(乘以一个基于数字在RUC内的位置的因子(从RUC的右侧开始(,并将这些乘法的所有结果相加:

    RUC:             8       0       0       0       9       7       3       5
    Position:        7       6       5       4       3       2       1       0
    Multiplications: 8x(7+2) 0x(6+2) 0x(5+2) 0x(4+2) 9x(3+2) 7x(2+2) 3x(1+2) 5x(0+2)
    Results:         72      0       0       0       45      28      9       10
    Sum of results:  164
    
  2. 将总和除以11,并使用除法的余数来确定验证数字:

    • 如果余数大于1,则验证数字为11 - remainder
    • 如果余数为01,则验证数字为0

    输入输出示例:

    Sum of results:       164
    Division:             164 / 11    ==>   quotient 14, remainder 10
    Verification digit:   11 - 10     ==>   1
    

这是我的Python版本的公式:

def calculate_dv_of_ruc(input_str):
# assure that we have a string
if not isinstance(input_str, str):
input_str = str(input_str)
# try to convert to 'int' to validate that it contains only digits.
# I suspect that this is faster than checking each char independently
int(input_str)
base = 11
k = 2
the_sum = 0
for i, c in enumerate(reversed(input_str)):
if k > base:
# reset to start value
k = 2
the_sum += k * int(c)
k += 1
_, rem = divmod(the_sum, base)
if rem > 1:
dv = base - rem
else:
dv = 0
return dv

测试此函数时,它会返回预期结果,当输入的字符不是数字时会引发错误:

>>> calculate_dv_of_ruc(80009735)
1
>>> calculate_dv_of_ruc('80009735')
1
>>> calculate_dv_of_ruc('80009735A')
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 8, in calculate_dv_of_ruc
ValueError: invalid literal for int() with base 10: '80009735A'

最新更新