Trust-Code/odoo-brasil

View on GitHub
br_base/tools/fiscal.py

Summary

Maintainability
F
3 days
Test Coverage
# -*- coding: utf-8 -*-
# © 2013  Renato Lima - Akretion
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import re

PARAMETERS = {
    'ac': {'tam': 13, 'val_tam': 11, 'starts_with': '01'},
    'al': {'tam': 9, 'starts_with': '24'},
    'am': {'tam': 9},
    'ce': {'tam': 9},
    'df': {'tam': 13, 'val_tam': 11, 'starts_with': '07'},
    'es': {'tam': 9},
    'ma': {'tam': 9, 'starts_with': '12'},
    'mt': {'tam': 11, 'prod': [3, 2, 9, 8, 7, 6, 5, 4, 3, 2]},
    'ms': {'tam': 9, 'starts_with': '28'},
    'pa': {'tam': 9, 'starts_with': '15'},
    'pb': {'tam': 9},
    'pr': {'tam': 10, 'val_tam': 8, 'prod': [3, 2, 7, 6, 5, 4, 3, 2]},
    'pi': {'tam': 9},
    'rj': {'tam': 8, 'prod': [2, 7, 6, 5, 4, 3, 2]},
    'rn': {'tam': 10, 'val_tam': 9, 'prod': [10, 9, 8, 7, 6, 5, 4, 3, 2]},
    'rs': {'tam': 10},
    'rr': {'tam': 9, 'starts_with': '24', 'prod': [1, 2, 3, 4, 5, 6, 7, 8],
           'div': 9},
    'sc': {'tam': 9},
    'se': {'tam': 9}
}


def validate_ie_param(uf, inscr_est):

    if uf not in PARAMETERS:
        return True

    tam = PARAMETERS[uf].get('tam', 0)
    inscr_est = unicode(inscr_est).strip().rjust(int(tam), u'0')
    inscr_est = re.sub('[^0-9]', '', inscr_est)
    val_tam = PARAMETERS[uf].get('val_tam', tam - 1)

    if isinstance(tam, list):
        i = tam.find(len(inscr_est))
        if i == -1:
            return False
        else:
            val_tam = val_tam[i]
    else:
        if len(inscr_est) != tam:
            return False

    sw = PARAMETERS[uf].get('starts_with', '')
    if not inscr_est.startswith(sw):
        return False

    inscr_est_ints = [int(c) for c in inscr_est]
    nova_ie = inscr_est_ints[:val_tam]
    prod = PARAMETERS[uf].get('prod', [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2])
    prod = prod[-val_tam:]

    while len(nova_ie) < tam:
        r = (sum([x * y for (x, y) in zip(nova_ie, prod)]) %
             PARAMETERS[uf].get('div', 11))
        if r > 1:
            f = 11 - r
        else:
            f = 0

        if uf not in 'rr':
            nova_ie.append(f)
        else:
            nova_ie.append(r)
        prod.insert(0, prod[0] + 1)

    # Se o número gerado coincidir com o número original, é válido
    return nova_ie == inscr_est_ints


def validate_ie_ap(inscr_est):
    inscr_est = re.sub('[^0-9]', '', inscr_est)

    # verificando o tamanho da inscrição estadual
    if len(inscr_est) != 9:
        return False

    # verificando os dois primeiros dígitos
    if not inscr_est.startswith('03'):
        return False

    # Pega apenas os 8 primeiros dígitos da inscrição estadual e
    # define os valores de 'p' e 'd'
    inscr_est_int = int(inscr_est[:8])
    if inscr_est_int <= 3017000:
        inscr_est_p = 5
        inscr_est_d = 0
    elif inscr_est_int <= 3019022:
        inscr_est_p = 9
        inscr_est_d = 1
    else:
        inscr_est_p = 0
        inscr_est_d = 0

    # Pega apenas os 8 primeiros dígitos da inscrição estadual e
    # gera o dígito verificador
    inscr_est = map(int, inscr_est)
    nova_ie = inscr_est[:8]

    prod = [9, 8, 7, 6, 5, 4, 3, 2]
    r = (inscr_est_p + sum([x * y for (x, y) in zip(nova_ie, prod)])) % 11
    if r > 1:
        f = 11 - r
    elif r == 1:
        f = 0
    else:
        f = inscr_est_d
    nova_ie.append(f)

    return nova_ie == inscr_est


def validate_ie_ba(inscr_est):
    inscr_est = re.sub('[^0-9]', '', inscr_est)
    inscr_est = map(int, inscr_est)

    # verificando o tamanho da inscrição estadual
    if len(inscr_est) == 8:
        tam = 8
        val_tam = 6
        test_digit = 0
    elif len(inscr_est) == 9:
        tam = 9
        val_tam = 7
        test_digit = 1
    else:
        return False

    nova_ie = inscr_est[:val_tam]

    prod = [8, 7, 6, 5, 4, 3, 2][-val_tam:]

    if inscr_est[test_digit] in [0, 1, 2, 3, 4, 5, 8]:
        modulo = 10
    else:
        modulo = 11

    while len(nova_ie) < tam:
        r = sum([x * y for (x, y) in zip(nova_ie, prod)]) % modulo
        if r > 0:
            f = modulo - r
        else:
            f = 0

        if f >= 10 and modulo == 11:
            f = 0

        if len(nova_ie) == val_tam:
            nova_ie.append(f)
        else:
            nova_ie.insert(val_tam, f)
        prod.insert(0, prod[0] + 1)

    return nova_ie == inscr_est


def validate_ie_go(inscr_est):
    inscr_est = re.sub('[^0-9]', '', inscr_est)

    # verificando o tamanho da inscrição estadual
    if len(inscr_est) != 9:
        return False

    # verificando os dois primeiros dígitos
    if not inscr_est[:2] in ['10', '11', '15']:
        return False

    # Pega apenas os 8 primeiros dígitos da inscrição estadual e
    # define os valores de 'p' e 'd'
    inscr_est_int = int(inscr_est[:8])
    if inscr_est_int >= 10103105 and inscr_est_int <= 10119997:
        inscr_est_d = 1
    else:
        inscr_est_d = 0

    # Pega apenas os 8 primeiros dígitos da inscrição estadual e
    # gera o dígito verificador
    inscr_est = map(int, inscr_est)
    nova_ie = inscr_est[:8]

    prod = [9, 8, 7, 6, 5, 4, 3, 2]
    r = sum([x * y for (x, y) in zip(nova_ie, prod)]) % 11
    if r > 1:
        f = 11 - r
    elif r == 1:
        f = inscr_est_d
    else:
        f = 0
    nova_ie.append(f)

    return nova_ie == inscr_est


def validate_ie_mg(inscr_est):
    inscr_est = re.sub('[^0-9]', '', inscr_est)

    # verificando o tamanho da inscrição estadual
    if len(inscr_est) != 13:
        return False

    # Pega apenas os 11 primeiros dígitos da inscrição estadual e
    # gera os dígitos verificadores
    inscr_est = map(int, inscr_est)
    nova_ie = inscr_est[:11]

    nova_ie_aux = list(nova_ie)
    nova_ie_aux.insert(3, 0)
    prod = [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
    r = str([x * y for (x, y) in zip(nova_ie_aux, prod)])
    r = re.sub('[^0-9]', '', r)
    r = map(int, r)
    r = sum(r)
    r2 = (r / 10 + 1) * 10
    r = r2 - r

    if r >= 10:
        r = 0

    nova_ie.append(r)

    prod = [3, 2, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2]
    r = sum([x * y for (x, y) in zip(nova_ie, prod)]) % 11
    if r > 1:
        f = 11 - r
    else:
        f = 0
    nova_ie.append(f)

    return nova_ie == inscr_est


def validate_ie_pe(inscr_est):
    inscr_est = re.sub('[^0-9]', '', inscr_est)

    # verificando o tamanho da inscrição estadual
    if (len(inscr_est) != 9) and (len(inscr_est) != 14):
        return False

    inscr_est = map(int, inscr_est)

    # verificando o tamanho da inscrição estadual
    if len(inscr_est) == 9:

        # Pega apenas os 7 primeiros dígitos da inscrição estadual e
        # gera os dígitos verificadores
        inscr_est = map(int, inscr_est)
        nova_ie = inscr_est[:7]

        prod = [8, 7, 6, 5, 4, 3, 2]
        while len(nova_ie) < 9:
            r = sum([x * y for (x, y) in zip(nova_ie, prod)]) % 11
            if r > 1:
                f = 11 - r
            else:
                f = 0
            nova_ie.append(f)
            prod.insert(0, 9)
    elif len(inscr_est) == 14:

        # Pega apenas os 13 primeiros dígitos da inscrição estadual e
        # gera o dígito verificador
        inscr_est = map(int, inscr_est)
        nova_ie = inscr_est[:13]

        prod = [5, 4, 3, 2, 1, 9, 8, 7, 6, 5, 4, 3, 2]
        r = sum([x * y for (x, y) in zip(nova_ie, prod)]) % 11
        f = 11 - r
        if f > 10:
            f = f - 10
        nova_ie.append(f)

    return nova_ie == inscr_est


def validate_ie_ro(inscr_est):
    def gera_digito_ro(nova_ie, prod):
        r = sum([x * y for (x, y) in zip(nova_ie, prod)]) % 11
        f = 11 - r
        if f > 9:
            f = f - 10
        return f

    inscr_est = re.sub('[^0-9]', '', inscr_est)
    inscr_est = map(int, inscr_est)

    # verificando o tamanho da inscrição estadual
    if len(inscr_est) == 9:
        # Despreza-se os 3 primeiros dígitos, pega apenas os 8 primeiros
        # dígitos da inscrição estadual e gera o dígito verificador
        nova_ie = inscr_est[3:8]

        prod = [6, 5, 4, 3, 2]
        f = gera_digito_ro(nova_ie, prod)
        nova_ie.append(f)

        nova_ie = inscr_est[0:3] + nova_ie
    elif len(inscr_est) == 14:
        # Pega apenas os 13 primeiros dígitos da inscrição estadual e
        # gera o dígito verificador
        nova_ie = inscr_est[:13]

        prod = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
        f = gera_digito_ro(nova_ie, prod)
        nova_ie.append(f)
    else:
        return False

    return nova_ie == inscr_est


def validate_ie_sp(inscr_est):
    def gera_digito_sp(nova_ie, prod):
        r = sum([x * y for (x, y) in zip(nova_ie, prod)]) % 11
        if r < 10:
            return r
        elif r == 10:
            return 0
        else:
            return 1

    # Industriais e comerciais
    if inscr_est[0] != 'P':

        inscr_est = re.sub('[^0-9]', '', inscr_est)

        # verificando o tamanho da inscrição estadual
        if len(inscr_est) != 12:
            return False

        # Pega apenas os 8 primeiros dígitos da inscrição estadual e
        # gera o primeiro dígito verificador
        inscr_est = map(int, inscr_est)
        nova_ie = inscr_est[:8]

        prod = [1, 3, 4, 5, 6, 7, 8, 10]
        f = gera_digito_sp(nova_ie, prod)
        nova_ie.append(f)

        # gera o segundo dígito verificador
        nova_ie.extend(inscr_est[9:11])
        prod = [3, 2, 10, 9, 8, 7, 6, 5, 4, 3, 2]
        f = gera_digito_sp(nova_ie, prod)
        nova_ie.append(f)

    # Produtor rural
    else:
        inscr_est = re.sub('[^0-9]', '', inscr_est)

        # verificando o tamanho da inscrição estadual
        if len(inscr_est) != 12:
            return False

        # verificando o primeiro dígito depois do 'P'
        if inscr_est[0] != '0':
            return False

        # Pega apenas os 8 primeiros dígitos da inscrição estadual e
        # gera o dígito verificador
        inscr_est = map(int, inscr_est)
        nova_ie = inscr_est[:8]

        prod = [1, 3, 4, 5, 6, 7, 8, 10]
        f = gera_digito_sp(nova_ie, prod)
        nova_ie.append(f)

        nova_ie.extend(inscr_est[9:])

    return nova_ie == inscr_est


def validate_ie_to(inscr_est):
    inscr_est = re.sub('[^0-9]', '', inscr_est)

    # verificando o tamanho da inscrição estadual
    if len(inscr_est) == 11:

        # verificando os dígitos 3 e 4
        if not inscr_est[2:4] in ['01', '02', '03', '99']:
            return False

        # Pega apenas os dígitos que entram no cálculo
        inscr_est = map(int, inscr_est)
        nova_ie = inscr_est[:2] + inscr_est[4:10]

    # Contemplando o novo IE de Tocantins de 9 digitos
    elif len(inscr_est) == 9:
        inscr_est = map(int, inscr_est)
        nova_ie = inscr_est[:8]

    else:
        return False

    prod = [9, 8, 7, 6, 5, 4, 3, 2]
    r = sum([x * y for (x, y) in zip(nova_ie, prod)]) % 11
    if r > 1:
        f = 11 - r
    else:
        f = 0
    nova_ie.append(f)

    # Se o IE for antigo, adicionar os digitos 3 e 4
    if len(inscr_est) == 11:
        nova_ie = nova_ie[:2] + inscr_est[2:4] + nova_ie[2:]

    return nova_ie == inscr_est


def validate_cnpj(cnpj):
    """ Rotina para validação do CNPJ - Cadastro Nacional
    de Pessoa Juridica.

    :param string cnpj: CNPJ para ser validado

    :return bool: True or False
    """
    # Limpando o cnpj
    if not cnpj.isdigit():
        cnpj = re.sub('[^0-9]', '', cnpj)

    # verificando o tamano do  cnpj
    if len(cnpj) != 14:
        return False

    # Pega apenas os 12 primeiros dígitos do CNPJ e gera os digitos
    cnpj = map(int, cnpj)
    novo = cnpj[:12]

    prod = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
    while len(novo) < 14:
        r = sum([x * y for (x, y) in zip(novo, prod)]) % 11
        if r > 1:
            f = 11 - r
        else:
            f = 0
        novo.append(f)
        prod.insert(0, 6)

    # Se o número gerado coincidir com o número original, é válido
    if novo == cnpj:
        return True

    return False


def validate_cpf(cpf):
    """Rotina para validação do CPF - Cadastro Nacional
    de Pessoa Física.

    :Return: True or False

    :Parameters:
      - 'cpf': CPF to be validate.
    """
    if not cpf.isdigit():
        cpf = re.sub('[^0-9]', '', cpf)

    if len(cpf) != 11:
        return False

    # Pega apenas os 9 primeiros dígitos do CPF e gera os 2 dígitos
    cpf = map(int, cpf)
    novo = cpf[:9]

    while len(novo) < 11:
        r = sum([(len(novo) + 1 - i) * v for i, v in enumerate(novo)]) % 11

        if r > 1:
            f = 11 - r
        else:
            f = 0
        novo.append(f)

    # Se o número gerado coincidir com o número original, é válido
    if novo == cpf:
        return True

    return False