From 730944a94e1407b8a410ad634b4e51bbea7ff588 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:35:13 -0300 Subject: [PATCH 01/52] Novos Requisitos --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ec7dc2f..1ac3664 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ Biblioteca para geração dos arquivos do Sistema Público de Escrituração Dig * python * six + * coveralls + * pytest + * cchardet + * xlsxwriter ## Como instalar From 1dc16f28efa0d616e19a230b5724ccb83989e0bd Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:38:26 -0300 Subject: [PATCH 02/52] novos requisitos: cchardet e xlsxwriter --- requeriments.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requeriments.txt b/requeriments.txt index 57c231d..489bb8c 100644 --- a/requeriments.txt +++ b/requeriments.txt @@ -1,3 +1,5 @@ coveralls==0.5 six==1.9.0 pytest==2.6.4 +cchardet==2.1.5 +xlsxwriter=1.2.7 From 1585e9447eb6bb21a71931768a920156250c185e Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:42:35 -0300 Subject: [PATCH 03/52] add install_requires: cchardet e xlsxwriter --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6a89b0e..79a2e69 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,7 @@ def run_tests(self): 'Programming Language :: Python :: 3.6', ], keywords='sped fiscal contábil contabilidade receita federal', - install_requires=['six'], + install_requires=['six','cchardet','xlsxwriter'], tests_require=['pytest'], extras_require={ 'dev': ['pylint>=1.9.1'], From f3a4c33453545cbe81b2da71691a0d4a18fbcb29 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:43:59 -0300 Subject: [PATCH 04/52] =?UTF-8?q?nova=20vers=C3=A3o:=201.0.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sped/__init__.py b/sped/__init__.py index 73aff5c..82dbebe 100644 --- a/sped/__init__.py +++ b/sped/__init__.py @@ -7,4 +7,4 @@ from .escrituracao import Escrituracao -__version__ = '1.0.2' +__version__ = '1.0.3' From 28ddda71b9e86be1e007850e17291a7d27c0f192 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:46:01 -0300 Subject: [PATCH 05/52] =?UTF-8?q?testar=20leitura=5Fcompleta=20e=20adicion?= =?UTF-8?q?ar=20op=C3=A7=C3=A3o=20de=20codifica=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/arquivos.py | 51 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/sped/arquivos.py b/sped/arquivos.py index a6a0ea5..982a603 100644 --- a/sped/arquivos.py +++ b/sped/arquivos.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- - +import re from collections import OrderedDict from io import StringIO from .registros import RegistroIndefinido - class ArquivoDigital(object): registros = None blocos = None @@ -18,30 +17,56 @@ def __init__(self): self._registro_abertura = self.registro_abertura() self._registro_encerramento = self.registro_encerramento() self._blocos = OrderedDict() - - def readfile(self, filename): - with open(filename) as spedfile: - for line in [line.rstrip('\r\n') for line in spedfile]: - self.read_registro(line.decode('utf8')) + self.leitura_completa = False + + def readfile(self, filename, codificacao=None, verbose=None): + if codificacao is None: # 'utf-8', 'latin-1', ... + codificacao = 'utf-8' + with open(filename, 'r', encoding=codificacao, errors='ignore') as spedfile: + for line in [line.strip() for line in spedfile]: + # A simple way to remove multiple spaces in a string + line = re.sub(r'\s{2,}', ' ', line) + # Em algumas EFDs foram encontrados registros digitados incorretamente em minúsculo. + # Por exemplo, o registro 'c491' deve ser corrigido para 'C491'. + line = line[:6].upper() + line[6:] # line = '|c491|...' --> '|C491|...' + self.read_registro(line) + # Verificar se o arquivo SPED foi lido até a última linha válida que contém o registro '9999'. + if self.leitura_completa: + break + if not self.leitura_completa: + raise RuntimeError(u"\nOcorreu uma falha ao ler o arquivo: '%s'.\n" % filename) + elif verbose: + print(u"O arquivo SPED '%s' foi lido com sucesso.\n" % filename) def read_registro(self, line): reg_id = line.split('|')[1] - + try: - registro_class = getattr(self.__class__.registros, - 'Registro' + reg_id) + # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance + # Devo substituir 'self.__class__.registros' por 'type(self).registros' ? + registro_class = getattr(self.__class__.registros, 'Registro' + reg_id) except AttributeError: - raise RuntimeError(u"Arquivo inválido para EFD - PIS/COFINS") + raise RuntimeError(u"Arquivo inválido para EFD - PIS/COFINS. Registro: %s" % reg_id) registro = registro_class(line) + bloco_id = reg_id[0] + bloco = self._blocos[bloco_id] if registro.__class__ == self.__class__.registro_abertura: + # Atualizar o registro de abertura 0000 do SPED self._registro_abertura = registro elif registro.__class__ == self.__class__.registro_encerramento: + # Atualizar o registro de encerramento 9999 do SPED self._registro_encerramento = registro + self.leitura_completa = True + elif registro.__class__ == bloco.registro_abertura.__class__: + # Atualizar os registros de abertura dos blocos: 0001, A001, C001, ... + bloco.registro_abertura = registro + elif registro.__class__ == bloco.registro_encerramento.__class__: + # Atualizar os registros de encerramento dos blocos: 0990, A990, C990, ... + bloco.registro_encerramento = registro else: - bloco_id = reg_id[0] - bloco = self._blocos[bloco_id] + # Adicionar informações dos registros a cada linha obtida de filename bloco.add(registro) def write_to(self, buff): From bf8af8469198736b1c23c48e7ba56de991df3dca Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:48:03 -0300 Subject: [PATCH 06/52] =?UTF-8?q?remover=20a=20condi=C3=A7=C3=A3o=20de=20r?= =?UTF-8?q?egistro=20de=20abertura=20e=20encerramento=20dos=20blocos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/blocos.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sped/blocos.py b/sped/blocos.py index 8f2d497..8da85c3 100644 --- a/sped/blocos.py +++ b/sped/blocos.py @@ -2,7 +2,6 @@ from .registros import Registro - class Bloco(object): def __init__(self, nome=''): self._nome = nome @@ -14,12 +13,10 @@ def __repr__(self): @property def abertura(self): - # Define o indicador de movimento ou dados return self.registro_abertura @property def encerramento(self): - # Define a quantidade de registros return self.registro_encerramento @property @@ -27,7 +24,4 @@ def registros(self): return [self.abertura] + self._registros + [self.encerramento] def add(self, registro): - # Não adiciona o registro de abertura e fechamento - if not registro.__class__ == self.registro_abertura.__class__ and \ - not registro.__class__ == self.registro_encerramento.__class__: - self._registros.append(registro) + self._registros.append(registro) From 050f6ac691c69fcc679fd1e98851c07d0640544a Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:53:48 -0300 Subject: [PATCH 07/52] =?UTF-8?q?[new]=20CampoChaveEletronica=20e=20format?= =?UTF-8?q?ar=20sa=C3=ADdas=20de=20CPF,=20CNPJ,=20Chave,=20...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/campos.py | 115 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 3 deletions(-) diff --git a/sped/campos.py b/sped/campos.py index 9c9f575..aae7308 100644 --- a/sped/campos.py +++ b/sped/campos.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- - import re from datetime import date @@ -188,6 +187,8 @@ def get(self, registro): return datetime.strptime(valor, '%d%m%Y').date() def set(self, registro, valor): + # https://stackoverflow.com/questions/19887353/attributeerror-str-object-has-no-attribute-strftime + valor = datetime.strptime(valor, '%d%m%Y') if isinstance(valor, date): super().set(registro, valor.strftime('%d%m%Y')) elif not valor: @@ -195,6 +196,14 @@ def set(self, registro, valor): else: raise FormatoInvalidoError(registro, self.nome) + @staticmethod + def formatar(data_in): + dt = datetime.strptime(data_in, "%d%m%Y") # ddmmaaaa + #data_out = dt.isoformat('T') + #data_out = dt.strftime('%x %X') # excel date format + data_out = dt.strftime("%d/%m/%Y") + return data_out + class CampoRegex(Campo): def __init__(self, indice, nome, obrigatorio=False, regex=None): @@ -216,7 +225,11 @@ def set(self, registro, valor): class CampoCNPJ(Campo): @staticmethod def validar(valor): - if len(valor) != 14: + # valor = '53.939.351/0001-29' + # remover os caracteres não dígitos (\D) + valor = re.sub(r'\D', '', valor) + + if not re.search(r'^\d{14}$', str(valor)): return False multiplicadores = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] @@ -239,11 +252,26 @@ def validar(valor): return True + @staticmethod + def formatar(cnpj): + cnpj = re.sub(r'\D', '', cnpj) + mensagem_de_validacao = '' + if len(cnpj) >= 1: + if not CampoCNPJ.validar(cnpj): + mensagem_de_validacao = ' : dígito verificador do cnpj inválido!' + if len(cnpj) == 14: + cnpj = "%s.%s.%s/%s-%s" % (cnpj[0:2],cnpj[2:5],cnpj[5:8],cnpj[8:12],cnpj[12:14]) + return cnpj + mensagem_de_validacao + class CampoCPF(Campo): @staticmethod def validar(valor): - if len(valor) != 11: + # valor = '333.333.333-33' + # remover os caracteres não dígitos (\D) + valor = re.sub(r'\D', '', valor) + + if not re.search(r'^\d{11}$', str(valor)): return False multiplicadores = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2] @@ -265,13 +293,94 @@ def validar(valor): return False return True + + @staticmethod + def formatar(cpf): + cpf = re.sub(r'\D', '', cpf) + mensagem_de_validacao = '' + if len(cpf) >= 1: + if not CampoCPF.validar(cpf): + mensagem_de_validacao = ' : dígito verificador do cpf inválido!' + if len(cpf) == 11: + cpf = "%s.%s.%s-%s" % (cpf[0:3],cpf[3:6],cpf[6:9],cpf[9:11]) + return cpf + mensagem_de_validacao class CampoCPFouCNPJ(Campo): @staticmethod def validar(valor): + # remover os caracteres não dígitos (\D) + valor = re.sub(r'\D', '', valor) + if len(valor) == 14: return CampoCNPJ.validar(valor) if len(valor) == 11: return CampoCPF.validar(valor) return False + + @staticmethod + def formatar(digt): + digt = re.sub(r'\D', '', digt) + mensagem_de_validacao = '' + if len(digt) >= 1: + if len(digt) == 11 and not CampoCPF.validar(digt): + mensagem_de_validacao = ' : dígito verificador do cpf inválido!' + elif len(digt) == 14 and not CampoCNPJ.validar(digt): + mensagem_de_validacao = ' : dígito verificador do cnpj inválido!' + + if len(digt) == 11: + digt = "CPF %s.%s.%s-%s" % (digt[0:3],digt[3:6],digt[6:9],digt[9:11]) + elif len(digt) == 14: + digt = "CNPJ %s.%s.%s/%s-%s" % (digt[0:2],digt[2:5],digt[5:8],digt[8:12],digt[12:14]) + return digt + mensagem_de_validacao + + +# Fonte: 'NFe Manual_de_Orientacao_Contribuinte_v_6.00.pdf', pg 144. +# 5.4 Cálculo do Dígito Verificador da Chave de Acesso da NF-e +class CampoChaveEletronica(Campo): + @staticmethod + def validar(valor): + # remover os caracteres não dígitos (\D) + valor = re.sub(r'\D', '', valor) + + if not re.search(r'^\d{44}$', str(valor)): + return False + + chave = [int(digito) for digito in valor] + multiplicadores = [4, 3, 2] + [9, 8, 7, 6, 5, 4, 3, 2] * 5 + [0] + + soma = sum([chave[i] * multiplicadores[i] for i in range(44)]) + + resto_da_divisao = soma % 11 + digito_verificador = 11 - resto_da_divisao + + if digito_verificador >= 10: + digito_verificador = 0 + + if chave[-1] != digito_verificador: + return False + + # dentro da chave eletrônica há o CNPJ do emitente + # que também será verificado + cnpj = str(valor)[6:20] + + return CampoCNPJ.validar(cnpj) + + @staticmethod + def formatar(chave): + chave = re.sub(r'\D', '', chave) + mensagem_de_validacao = '' + if len(chave) >= 1: + if not CampoChaveEletronica.validar(chave): + mensagem_de_validacao = ' : dígito verificador da chave inválido!' + if len(chave) == 44: + chave = "%s.%s.%s.%s.%s.%s.%s.%s-%s" % (chave[0:2],chave[2:6],chave[6:20],chave[20:22],chave[22:25],chave[25:34],chave[34:35],chave[35:43],chave[43:44]) + return chave + mensagem_de_validacao + + +class CampoNCM(Campo): + @staticmethod + def formatar(ncm): + if len(ncm) == 8: + ncm = "%s.%s.%s" % (ncm[0:4],ncm[4:6],ncm[6:8]) + return ncm \ No newline at end of file From f1f8c33fa492778a3f65eee4c5d476d91f611142 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:58:24 -0300 Subject: [PATCH 08/52] [new] numero_da_linha --- sped/registros.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/sped/registros.py b/sped/registros.py index 8a60e45..a922bcd 100644 --- a/sped/registros.py +++ b/sped/registros.py @@ -6,7 +6,7 @@ from .erros import CampoError from .erros import CampoInexistenteError from .erros import RegistroError - +import itertools class Registro(object): """ @@ -64,6 +64,7 @@ class Registro(object): FormatoInvalidoError: RegistroTest -> RETIFICADORA """ campos = [] + contador_de_linhas = itertools.count(1) def __init__(self, line=None): if not line: @@ -71,16 +72,24 @@ def __init__(self, line=None): for c in self.campos: if isinstance(c, CampoFixo): self._valores[c.indice] = c.valor + self._numero_da_linha = None else: - self._valores = line.split('|') + #self._valores = line.split('|') + self._valores = [valor.strip() for valor in line.split('|')] for c in self.campos: if isinstance(c, CampoFixo): if self._valores[c.indice] != c.valor: raise CampoError(self, c.nome) + # Inicializar contador na leitura do registro de abertura '0000' + # if self.__class__.__name__ == 'Registro0000': + if self._valores[1] == '0000': + Registro.contador_de_linhas = itertools.count(1) + # Informação do número da linha do arquivo sped + self._numero_da_linha = next(Registro.contador_de_linhas) @property - def campos(self): - return self.__class__.campos + def numero_da_linha(self): + return self._numero_da_linha @property def valores(self): @@ -122,7 +131,6 @@ def __str__(self): def __repr__(self): return '<%s.%s>' % (self.__class__.__module__, self.__class__.__name__) - class RegistroIndefinido(Registro): def __init__(self): super(RegistroIndefinido, self).__init__() From 111fa0988401a84bed732aa3611933db881983a2 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 22:59:36 -0300 Subject: [PATCH 09/52] =?UTF-8?q?[new]=20nivel=20e=20atualiza=C3=A7=C3=A3o?= =?UTF-8?q?=20dos=20registros?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/efd/icms_ipi/registros.py | 2319 ++++++++++++++++++++++---------- 1 file changed, 1593 insertions(+), 726 deletions(-) diff --git a/sped/efd/icms_ipi/registros.py b/sped/efd/icms_ipi/registros.py index 78d3032..9b08a64 100644 --- a/sped/efd/icms_ipi/registros.py +++ b/sped/efd/icms_ipi/registros.py @@ -5,7 +5,12 @@ from ...campos import CampoData from ...campos import CampoFixo from ...campos import CampoNumerico - +from ...campos import CampoAlfanumerico +from ...campos import CampoRegex +from ...campos import CampoCNPJ +from ...campos import CampoCPF +from ...campos import CampoCPFouCNPJ +from ...campos import CampoChaveEletronica class Registro0000(Registro): """ @@ -18,17 +23,18 @@ class Registro0000(Registro): CampoData(4, 'DT_INI'), CampoData(5, 'DT_FIN'), Campo(6, 'NOME'), - Campo(7, 'CNPJ'), - Campo(8, 'CPF'), + CampoCNPJ(7, 'CNPJ'), + CampoCPF(8, 'CPF'), Campo(9, 'UF'), Campo(10, 'IE'), - Campo(11, 'COD_MUN'), + CampoNumerico(11, 'COD_MUN'), Campo(12, 'IM'), Campo(13, 'SUFRAMA'), Campo(14, 'IND_PERFIL'), Campo(15, 'IND_ATIV'), ] + nivel = 0 class Registro0001(Registro): """ @@ -39,6 +45,7 @@ class Registro0001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class Registro0005(Registro): """ @@ -57,6 +64,7 @@ class Registro0005(Registro): Campo(10, 'EMAIL'), ] + nivel = 2 class Registro0015(Registro): """ @@ -68,6 +76,7 @@ class Registro0015(Registro): Campo(3, 'IE_ST'), ] + nivel = 2 class Registro0100(Registro): """ @@ -76,9 +85,9 @@ class Registro0100(Registro): campos = [ CampoFixo(1, 'REG', '0100'), Campo(2, 'NOME'), - Campo(3, 'CPF'), + CampoCPF(3, 'CPF'), Campo(4, 'CRC'), - Campo(5, 'CNPJ'), + CampoCNPJ(5, 'CNPJ'), Campo(6, 'CEP'), Campo(7, 'END'), Campo(8, 'NUM'), @@ -87,9 +96,10 @@ class Registro0100(Registro): Campo(11, 'FONE'), Campo(12, 'FAX'), Campo(13, 'EMAIL'), - Campo(14, 'COD_MUN'), + CampoNumerico(14, 'COD_MUN'), ] + nivel = 2 class Registro0150(Registro): """ @@ -100,10 +110,10 @@ class Registro0150(Registro): Campo(2, 'COD_PART'), Campo(3, 'NOME'), Campo(4, 'COD_PAIS'), - Campo(5, 'CNPJ'), - Campo(6, 'CPF'), + CampoCNPJ(5, 'CNPJ'), + CampoCPF(6, 'CPF'), Campo(7, 'IE'), - Campo(8, 'COD_MUN'), + CampoNumerico(8, 'COD_MUN'), Campo(9, 'SUFRAMA'), Campo(10, 'END'), Campo(11, 'NUM'), @@ -111,6 +121,7 @@ class Registro0150(Registro): Campo(13, 'BAIRRO'), ] + nivel = 2 class Registro0175(Registro): """ @@ -118,11 +129,12 @@ class Registro0175(Registro): """ campos = [ CampoFixo(1, 'REG', '0175'), - Campo(2, 'DT_ALT'), + CampoData(2, 'DT_ALT'), Campo(3, 'NR_CAMPO'), Campo(4, 'CONT_ANT'), ] + nivel = 3 class Registro0190(Registro): """ @@ -134,6 +146,7 @@ class Registro0190(Registro): Campo(3, 'DESCR'), ] + nivel = 2 class Registro0200(Registro): """ @@ -151,10 +164,11 @@ class Registro0200(Registro): Campo(9, 'EX_IPI'), Campo(10, 'COD_GEN'), Campo(11, 'COD_LST'), - Campo(12, 'ALIQ_ICMS'), + CampoNumerico(12, 'ALIQ_ICMS'), Campo(13, 'CEST'), ] + nivel = 2 class Registro0205(Registro): """ @@ -168,6 +182,7 @@ class Registro0205(Registro): Campo(5, 'COD_ANT_ITEM'), ] + nivel = 3 class Registro0206(Registro): """ @@ -178,6 +193,7 @@ class Registro0206(Registro): Campo(2, 'COD_COMB'), ] + nivel = 3 class Registro0210(Registro): """ @@ -190,6 +206,7 @@ class Registro0210(Registro): CampoNumerico(4, 'PERDA'), ] + nivel = 3 class Registro0220(Registro): """ @@ -201,6 +218,7 @@ class Registro0220(Registro): Campo(3, 'FAT_CONV'), ] + nivel = 3 class Registro0300(Registro): """ @@ -216,6 +234,7 @@ class Registro0300(Registro): Campo(7, 'NR_PARC'), ] + nivel = 2 class Registro0305(Registro): """ @@ -228,6 +247,7 @@ class Registro0305(Registro): Campo(4, 'VIDA_UTIL'), ] + nivel = 3 class Registro0400(Registro): """ @@ -239,6 +259,7 @@ class Registro0400(Registro): Campo(3, 'DESCR_NAT'), ] + nivel = 2 class Registro0450(Registro): """ @@ -250,6 +271,7 @@ class Registro0450(Registro): Campo(3, 'TXT'), ] + nivel = 2 class Registro0460(Registro): """ @@ -261,6 +283,7 @@ class Registro0460(Registro): Campo(3, 'TXT'), ] + nivel = 2 class Registro0500(Registro): """ @@ -268,7 +291,7 @@ class Registro0500(Registro): """ campos = [ CampoFixo(1, 'REG', '0500'), - Campo(2, 'DT_ALT'), + CampoData(2, 'DT_ALT'), Campo(3, 'COD_NAT_CC'), Campo(4, 'IND_CTA'), Campo(5, 'NÍVEL'), @@ -276,6 +299,7 @@ class Registro0500(Registro): Campo(7, 'NOME_CTA'), ] + nivel = 2 class Registro0600(Registro): """ @@ -283,11 +307,12 @@ class Registro0600(Registro): """ campos = [ CampoFixo(1, 'REG', '0600'), - Campo(2, 'DT_ALT'), + CampoData(2, 'DT_ALT'), Campo(3, 'COD_CCUS'), Campo(4, 'CCUS'), ] + nivel = 2 class Registro0990(Registro): """ @@ -298,6 +323,7 @@ class Registro0990(Registro): CampoNumerico(2, 'QTD_LIN_0'), ] + nivel = 1 class RegistroB001(Registro): """ @@ -305,9 +331,219 @@ class RegistroB001(Registro): """ campos = [ CampoFixo(1, 'REG', 'B001'), - Campo(2, 'IND_MOV', '1'), + Campo(2, 'IND_MOV'), + ] + + nivel = 1 + +class RegistroB020(Registro): + """ + NOTA FISCAL (CÓDIGO 01), NOTA FISCAL DE SERVIÇOS (CÓDIGO 03), + NOTA FISCAL DE SERVIÇOS AVULSA (CÓDIGO 3B), NOTA FISCAL DE PRODUTOR + (CÓDIGO 04), CONHECIMENTO DE TRANSPORTE RODOVIÁRIO DE CARGAS + (CÓDIGO 08), NF-e (CÓDIGO 55) e NFC-e (CÓDIGO 65). + """ + campos = [ + CampoFixo(1, 'REG', 'B020'), + Campo(2, 'IND_OPER'), + Campo(3, 'IND_EMIT'), + Campo(4, 'COD_PART'), + Campo(5, 'COD_MOD'), + CampoNumerico(6, 'COD_SIT'), + Campo(7, 'SER'), + CampoNumerico(8, 'NUM_DOC'), + CampoChaveEletronica(9, 'CHV_NFE'), + CampoData(10, 'DT_DOC'), + CampoNumerico(11, 'COD_MUN_SERV'), + CampoNumerico(12, 'VL_CONT'), + CampoNumerico(13, 'VL_MAT_TERC'), + CampoNumerico(14, 'VL_SUB'), + CampoNumerico(15, 'VL_ISNT_ISS'), + CampoNumerico(16, 'VL_DED_BC'), + CampoNumerico(17, 'VL_BC_ISS'), + CampoNumerico(18, 'VL_BC_ISS_RT'), + CampoNumerico(19, 'VL_ISS_RT'), + CampoNumerico(20, 'VL_ISS'), + Campo(21, 'COD_INF_OBS'), + ] + + nivel = 2 + +class RegistroB025(Registro): + """ + DETALHAMENTO POR COMBINAÇÃO DE ALÍQUOTA E ITEM DA + LISTA DE SERVIÇOS DA LC 116/2003) + """ + campos = [ + CampoFixo(1, 'REG', 'B025'), + CampoNumerico(2, 'VL_CONT_P'), + CampoNumerico(3, 'VL_BC_ISS_P'), + CampoNumerico(4, 'ALIQ_ISS'), + CampoNumerico(5, 'VL_ISS_P'), + CampoNumerico(6, 'VL_ISNT_ISS_P'), + Campo(7, 'COD_SERV'), + ] + + nivel = 3 + +class RegistroB030(Registro): + """ + NOTA FISCAL DE SERVIÇOS SIMPLIFICADA (CÓDIGO 3A) + """ + campos = [ + CampoFixo(1, 'REG', 'B030'), + Campo(2, 'COD_MOD'), + Campo(3, 'SER'), + CampoNumerico(4, 'NUM_DOC_INI'), + CampoNumerico(5, 'NUM_DOC_FIN'), + CampoData(6, 'DT_DOC'), + CampoNumerico(7, 'QTD_CANC'), + CampoNumerico(8, 'VL_CONT'), + CampoNumerico(9, 'VL_ISNT_ISS'), + CampoNumerico(10, 'VL_BC_ISS'), + CampoNumerico(11, 'VL_ISS'), + Campo(12, 'COD_INF_OBS'), + ] + + nivel = 2 + +class RegistroB035(Registro): + """ + DETALHAMENTO POR COMBINAÇÃO DE ALÍQUOTA E ITEM DA + LISTA DE SERVIÇOS DA LC 116/2003) + """ + campos = [ + CampoFixo(1, 'REG', 'B035'), + CampoNumerico(2, 'VL_CONT_P'), + CampoNumerico(3, 'VL_BC_ISS_P'), + CampoNumerico(4, 'ALIQ_ISS'), + CampoNumerico(5, 'VL_ISS_P'), + CampoNumerico(6, 'VL_ISNT_ISS_P'), + Campo(7, 'COD_SERV'), + ] + + nivel = 1 + +class RegistroB350(Registro): + """ + SERVIÇOS PRESTADOS POR INSTITUIÇÕES FINANCEIRAS + """ + campos = [ + CampoFixo(1, 'REG', 'B350'), + Campo(2, 'COD_CTD'), + Campo(3, 'CTA_ISS'), + Campo(4, 'CTA_COSIF'), + CampoNumerico(5, 'QTD_OCOR'), + Campo(6, 'COD_SERV'), + CampoNumerico(7, 'VL_CONT'), + CampoNumerico(8, 'VL_BC_ISS'), + CampoNumerico(9, 'ALIQ_ISS'), + CampoNumerico(10, 'VL_ISS'), + Campo(11, 'COD_INF_OBS'), + ] + + nivel = 2 + +class RegistroB420(Registro): + """ + TOTALIZAÇÃO DOS VALORES DE SERVIÇOS PRESTADOS POR + COMBINAÇÃO DE ALÍQUOTA E ITEM DA LISTA DE SERVIÇOS DA LC 116/200 + """ + campos = [ + CampoFixo(1, 'REG', 'B420'), + CampoNumerico(2, 'VL_CONT'), + CampoNumerico(3, 'VL_BC_ISS'), + CampoNumerico(4, 'ALIQ_ISS'), + CampoNumerico(5, 'VL_ISNT_ISS'), + CampoNumerico(6, 'VL_ISS'), + Campo(7, 'COD_SERV'), + ] + + nivel = 2 + +class RegistroB440(Registro): + """ + TOTALIZAÇÃO DOS VALORES RETIDOS + """ + campos = [ + CampoFixo(1, 'REG', 'B440'), + CampoNumerico(2, 'IND_OPER'), + Campo(3, 'COD_PART'), + CampoNumerico(4, 'VL_CONT_RT'), + CampoNumerico(5, 'VL_BC_ISS_RT'), + CampoNumerico(6, 'VL_ISS_RT') + ] + + nivel = 2 + +class RegistroB460(Registro): + """ + DEDUÇÕES DO ISS + """ + campos = [ + CampoFixo(1, 'REG', 'B460'), + Campo(2, 'IND_DED'), + CampoNumerico(3, 'VL_DED'), + Campo(4, 'NUM_PROC'), + Campo(5, 'IND_PROC'), + Campo(6, 'PROC'), + Campo(7, 'COD_INF_OBS'), + Campo(8, 'IND_OBR'), + ] + + nivel = 2 + +class RegistroB470(Registro): + """ + APURAÇÃO DO ISS + """ + campos = [ + CampoFixo(1, 'REG', 'B470'), + CampoNumerico(2, 'VL_CONT'), + CampoNumerico(3, 'VL_MAT_TERC'), + CampoNumerico(4, 'VL_MAT_PROP'), + CampoNumerico(5, 'VL_SUB'), + CampoNumerico(6, 'VL_ISNT'), + CampoNumerico(7, 'VL_DED_BC'), + CampoNumerico(8, 'VL_BC_ISS'), + CampoNumerico(9, 'VL_BC_ISS_RT'), + CampoNumerico(10, 'VL_ISS'), + CampoNumerico(11, 'VL_ISS_RT'), + CampoNumerico(12, 'VL_DED'), + CampoNumerico(13, 'VL_ISS_REC'), + CampoNumerico(14, 'VL_ISS_ST'), + CampoNumerico(15, 'VL_ISS_REC_UNI'), + ] + + nivel = 2 + +class RegistroB500(Registro): + """ + APURAÇÃO DO ISS SOCIEDADE UNIPROFISSIONA + """ + campos = [ + CampoFixo(1, 'REG', 'B500'), + CampoNumerico(2, 'VL_REC'), + CampoNumerico(3, 'QTD_PROF'), + CampoNumerico(4, 'VL_OR'), + ] + + nivel = 2 + +class RegistroB510(Registro): + """ + UNIPROFISSIONAL - EMPREGADOS E SÓCIOS + """ + campos = [ + CampoFixo(1, 'REG', 'B510'), + Campo(2, 'IND_PROF'), + Campo(3, 'IND_ESC'), + Campo(4, 'IND_SOC'), + CampoCPF(5, 'CPF'), + Campo(6, 'NOME'), ] + nivel = 3 class RegistroB990(Registro): """ @@ -315,9 +551,10 @@ class RegistroB990(Registro): """ campos = [ CampoFixo(1, 'REG', 'B990'), - CampoNumerico(2, 'QTD_LIN_B', 2), + CampoNumerico(2, 'QTD_LIN_B'), ] + nivel = 1 class RegistroC001(Registro): """ @@ -328,6 +565,7 @@ class RegistroC001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class RegistroC100(Registro): """ @@ -339,10 +577,10 @@ class RegistroC100(Registro): Campo(3, 'IND_EMIT'), Campo(4, 'COD_PART'), Campo(5, 'COD_MOD'), - Campo(6, 'COD_SIT'), + CampoNumerico(6, 'COD_SIT'), Campo(7, 'SER'), - Campo(8, 'NUM_DOC'), - Campo(9, 'CHV_NFE'), + CampoNumerico(8, 'NUM_DOC'), + CampoChaveEletronica(9, 'CHV_NFE'), CampoData(10, 'DT_DOC'), CampoData(11, 'DT_E_S'), CampoNumerico(12, 'VL_DOC'), @@ -365,6 +603,7 @@ class RegistroC100(Registro): CampoNumerico(29, 'VL_COFINS_ST'), ] + nivel = 2 class RegistroC101(Registro): """ @@ -374,11 +613,12 @@ class RegistroC101(Registro): """ campos = [ CampoFixo(1, 'REG', 'C101'), - Campo(2, 'VL_FCP_UF_DEST'), - Campo(3, 'VL_ICMS_UF_DEST'), - Campo(4, 'VL_ICMS_UF_REM'), + CampoNumerico(2, 'VL_FCP_UF_DEST'), + CampoNumerico(3, 'VL_ICMS_UF_DEST'), + CampoNumerico(4, 'VL_ICMS_UF_REM'), ] + nivel = 3 class RegistroC105(Registro): """ @@ -390,6 +630,7 @@ class RegistroC105(Registro): Campo(3, 'UF'), ] + nivel = 3 class RegistroC110(Registro): """ @@ -401,10 +642,11 @@ class RegistroC110(Registro): Campo(3, 'TXT_COMPL'), ] + nivel = 3 class RegistroC111(Registro): """ - PROCESSO REFERENCIADO (CÓDIGO 01, 1B, 04 E 55) + PROCESSO REFERENCIADO """ campos = [ CampoFixo(1, 'REG', 'C111'), @@ -412,10 +654,11 @@ class RegistroC111(Registro): Campo(3, 'IND_PROC'), ] + nivel = 4 class RegistroC112(Registro): """ - DOCUMENTO DE ARRECADAÇÃO REFERENCIADO (CÓDIGO 01, 1B, 04 E 55) + DOCUMENTO DE ARRECADAÇÃO REFERENCIADO """ campos = [ CampoFixo(1, 'REG', 'C112'), @@ -423,15 +666,16 @@ class RegistroC112(Registro): Campo(3, 'UF'), Campo(4, 'NUM_DA'), Campo(5, 'COD_AUT'), - Campo(6, 'VL_DA'), - Campo(7, 'DT_VCTO'), - Campo(8, 'DT_PGTO'), + CampoNumerico(6, 'VL_DA'), + CampoData(7, 'DT_VCTO'), + CampoData(8, 'DT_PGTO'), ] + nivel = 4 class RegistroC113(Registro): """ - DOCUMENTO FISCAL REFERENCIADO (CÓDIGO 01, 1B, 04 E 55) + DOCUMENTO FISCAL REFERENCIADO """ campos = [ CampoFixo(1, 'REG', 'C113'), @@ -440,25 +684,28 @@ class RegistroC113(Registro): Campo(4, 'COD_PART'), Campo(5, 'COD_MOD'), Campo(6, 'SER'), - Campo(7, 'SUB'), - Campo(8, 'NUM_DOC'), - Campo(9, 'DT_DOC'), + CampoNumerico(7, 'SUB'), + CampoNumerico(8, 'NUM_DOC'), + CampoData(9, 'DT_DOC'), + CampoChaveEletronica(10, 'CHV_DOCe'), ] + nivel = 4 class RegistroC114(Registro): """ - CUPOM FISCAL REFERENCIADO (CÓDIGO 01, 1B, 04 E 55) + CUPOM FISCAL REFERENCIADO """ campos = [ CampoFixo(1, 'REG', 'C114'), Campo(2, 'COD_MOD'), Campo(3, 'ECF_FAB'), Campo(4, 'ECF_CX'), - Campo(5, 'NUM_DOC'), - Campo(6, 'DT_DOC'), + CampoNumerico(5, 'NUM_DOC'), + CampoData(6, 'DT_DOC'), ] + nivel = 4 class RegistroC115(Registro): """ @@ -467,16 +714,17 @@ class RegistroC115(Registro): campos = [ CampoFixo(1, 'REG', 'C115'), Campo(2, 'IND_CARGA'), - Campo(3, 'CNPJ_COL'), + CampoCNPJ(3, 'CNPJ_COL'), Campo(4, 'IE_COL'), - Campo(5, 'CPF_COL'), - Campo(6, 'COD_MUN_COL'), - Campo(7, 'CNPJ_ENTG'), + CampoCPF(5, 'CPF_COL'), + CampoNumerico(6, 'COD_MUN_COL'), + CampoCNPJ(7, 'CNPJ_ENTG'), Campo(8, 'IE_ENTG'), - Campo(9, 'CPF_ENTG'), - Campo(10, 'COD_MUN_ENTG'), + CampoCPF(9, 'CPF_ENTG'), + CampoNumerico(10, 'COD_MUN_ENTG'), ] + nivel = 4 class RegistroC116(Registro): """ @@ -485,26 +733,29 @@ class RegistroC116(Registro): campos = [ CampoFixo(1, 'REG', 'C116'), Campo(2, 'COD_MOD'), - Campo(3, 'NR_SAT'), - Campo(4, 'CHV_CFE'), - Campo(5, 'NUM_CFE'), - Campo(6, 'DT_DOC'), + CampoNumerico(3, 'NR_SAT'), + CampoChaveEletronica(4, 'CHV_CFE'), + CampoNumerico(5, 'NUM_CFE'), + CampoData(6, 'DT_DOC'), ] + nivel = 4 class RegistroC120(Registro): """ - OPERAÇÕES DE IMPORTAÇÃO (CÓDIGO 01) + COMPLEMENTO DE DOCUMENTO - OPERAÇÕES DE IMPORTAÇÃO + (CÓDIGOS 01 e 55) """ campos = [ CampoFixo(1, 'REG', 'C120'), Campo(2, 'COD_DOC_IMP'), Campo(3, 'NUM_DOC IMP'), - Campo(4, 'PIS_IMP'), - Campo(5, 'COFINS_IMP'), + CampoNumerico(4, 'PIS_IMP'), + CampoNumerico(5, 'COFINS_IMP'), Campo(6, 'NUM_ACDRAW'), ] + nivel = 3 class RegistroC130(Registro): """ @@ -512,15 +763,16 @@ class RegistroC130(Registro): """ campos = [ CampoFixo(1, 'REG', 'C130'), - Campo(2, 'VL_SERV_NT'), - Campo(3, 'VL_BC_ISSQN'), - Campo(4, 'VL_ISSQN'), - Campo(5, 'VL_BC_IRRF'), - Campo(6, 'VL_ IRRF'), - Campo(7, 'VL_BC_PREV'), - Campo(8, 'VL_ PREV'), + CampoNumerico(2, 'VL_SERV_NT'), + CampoNumerico(3, 'VL_BC_ISSQN'), + CampoNumerico(4, 'VL_ISSQN'), + CampoNumerico(5, 'VL_BC_IRRF'), + CampoNumerico(6, 'VL_ IRRF'), + CampoNumerico(7, 'VL_BC_PREV'), + CampoNumerico(8, 'VL_ PREV'), ] + nivel = 3 class RegistroC140(Registro): """ @@ -532,10 +784,11 @@ class RegistroC140(Registro): Campo(3, 'IND_TIT'), Campo(4, 'DESC_TIT'), Campo(5, 'NUM_TIT'), - Campo(6, 'QTD_PARC'), - Campo(7, 'VL_TIT'), + CampoNumerico(6, 'QTD_PARC'), + CampoNumerico(7, 'VL_TIT'), ] + nivel = 3 class RegistroC141(Registro): """ @@ -543,11 +796,12 @@ class RegistroC141(Registro): """ campos = [ CampoFixo(1, 'REG', 'C141'), - Campo(2, 'NUM_PARC'), - Campo(3, 'DT_VCTO'), - Campo(4, 'VL_PARC'), + CampoNumerico(2, 'NUM_PARC'), + CampoData(3, 'DT_VCTO'), + CampoNumerico(4, 'VL_PARC'), ] + nivel = 4 class RegistroC160(Registro): """ @@ -557,16 +811,17 @@ class RegistroC160(Registro): CampoFixo(1, 'REG', 'C160'), Campo(2, 'COD_PART'), Campo(3, 'VEIC_ID'), - Campo(4, 'QTD_VOL'), - Campo(5, 'PESO_BRT'), - Campo(6, 'PESO_LIQ'), + CampoNumerico(4, 'QTD_VOL'), + CampoNumerico(5, 'PESO_BRT'), + CampoNumerico(6, 'PESO_LIQ'), Campo(7, 'UF_ID'), ] + nivel = 3 class RegistroC165(Registro): """ - OPERAÇÕES COM COMBUSTÍVEIS + OPERAÇÕES COM COMBUSTÍVEIS (CÓDIGO 01) """ campos = [ CampoFixo(1, 'REG', 'C165'), @@ -574,33 +829,34 @@ class RegistroC165(Registro): Campo(3, 'VEIC_ID'), Campo(4, 'COD_AUT'), Campo(5, 'NR_PASSE'), - Campo(6, 'HORA'), - Campo(7, 'TEMPER'), - Campo(8, 'QTD_VOL'), - Campo(9, 'PESO_BRT'), - Campo(10, 'PESO_LIQ'), + CampoNumerico(6, 'HORA'), + CampoNumerico(7, 'TEMPER'), + CampoNumerico(8, 'QTD_VOL'), + CampoNumerico(9, 'PESO_BRT'), + CampoNumerico(10, 'PESO_LIQ'), Campo(11, 'NOM_MOT'), - Campo(12, 'CPF'), + CampoCPF(12, 'CPF'), Campo(13, 'UF_ID'), ] + nivel = 3 class RegistroC170(Registro): """ - ITENS DO DOCUMENTO + ITENS DO DOCUMENTO (CÓDIGO 01, 1B, 04 e 55) """ campos = [ CampoFixo(1, 'REG', 'C170'), - CampoNumerico(2, 'NUM_ITEM'), - Campo(3, 'COD_ITEM'), + CampoNumerico(2, 'NUM_ITEM', obrigatorio=True), + Campo(3, 'COD_ITEM', obrigatorio=True), Campo(4, 'DESCR_COMPL'), CampoNumerico(5, 'QTD'), Campo(6, 'UNID'), - CampoNumerico(7, 'VL_ITEM'), + CampoNumerico(7, 'VL_ITEM', obrigatorio=True), CampoNumerico(8, 'VL_DESC'), Campo(9, 'IND_MOV'), - Campo(10, 'CST_ICMS'), - Campo(11, 'CFOP'), + CampoNumerico(10, 'CST_ICMS'), + CampoNumerico(11, 'CFOP', obrigatorio=True), Campo(12, 'COD_NAT'), CampoNumerico(13, 'VL_BC_ICMS'), CampoNumerico(14, 'ALIQ_ICMS'), @@ -614,22 +870,23 @@ class RegistroC170(Registro): CampoNumerico(22, 'VL_BC_IPI'), CampoNumerico(23, 'ALIQ_IPI'), CampoNumerico(24, 'VL_IPI'), - Campo(25, 'CST_PIS'), + CampoNumerico(25, 'CST_PIS', obrigatorio=True), CampoNumerico(26, 'VL_BC_PIS'), - CampoNumerico(27, 'ALIQ_PIS'), + CampoNumerico(27, 'ALIQ_PIS'), # 27 ALIQ_PIS em percentual CampoNumerico(28, 'QUANT_BC_PIS'), - CampoNumerico(29, 'ALIQ_PIS'), + CampoNumerico(29, 'ALIQ_PIS_REAIS'), # 27 ALIQ_PIS em reais: escolher nome diferente do nome do campo 27 CampoNumerico(30, 'VL_PIS'), - Campo(31, 'CST_COFINS'), + CampoNumerico(31, 'CST_COFINS', obrigatorio=True), CampoNumerico(32, 'VL_BC_COFINS'), - CampoNumerico(33, 'ALIQ_COFINS'), + CampoNumerico(33, 'ALIQ_COFINS'), # 33 ALIQ_COFINS em percentual CampoNumerico(34, 'QUANT_BC_COFINS'), - CampoNumerico(35, 'ALIQ_COFINS'), + CampoNumerico(35, 'ALIQ_COFINS_REAIS'), # 35 ALIQ_COFINS em reais: escolher nome diferente do nome do campo 33 CampoNumerico(36, 'VL_COFINS'), Campo(37, 'COD_CTA'), CampoNumerico(38, 'VL_ABAT_NT'), ] + nivel = 3 class RegistroC171(Registro): """ @@ -638,9 +895,10 @@ class RegistroC171(Registro): campos = [ CampoFixo(1, 'REG', 'C171'), Campo(2, 'NUM_TANQUE'), - Campo(3, 'QTDE'), + CampoNumerico(3, 'QTDE'), ] + nivel = 4 class RegistroC172(Registro): """ @@ -648,11 +906,12 @@ class RegistroC172(Registro): """ campos = [ CampoFixo(1, 'REG', 'C172'), - Campo(2, 'VL_BC_ISSQN'), - Campo(3, 'ALIQ_ISSQN'), - Campo(4, 'VL_ISSQN'), + CampoNumerico(2, 'VL_BC_ISSQN'), + CampoNumerico(3, 'ALIQ_ISSQN'), + CampoNumerico(4, 'VL_ISSQN'), ] + nivel = 4 class RegistroC173(Registro): """ @@ -661,14 +920,15 @@ class RegistroC173(Registro): campos = [ CampoFixo(1, 'REG', 'C173'), Campo(2, 'LOTE_MED'), - Campo(3, 'QTD_ITEM'), - Campo(4, 'DT_FAB'), - Campo(5, 'DT_VAL'), + CampoNumerico(3, 'QTD_ITEM'), + CampoData(4, 'DT_FAB'), + CampoData(5, 'DT_VAL'), Campo(6, 'IND_MED'), Campo(7, 'TP_PROD'), - Campo(8, 'VL_TAB_MAX'), + CampoNumerico(8, 'VL_TAB_MAX'), ] + nivel = 4 class RegistroC174(Registro): """ @@ -681,6 +941,7 @@ class RegistroC174(Registro): Campo(4, 'DESCR_COMPL'), ] + nivel = 4 class RegistroC175(Registro): """ @@ -689,28 +950,49 @@ class RegistroC175(Registro): campos = [ CampoFixo(1, 'REG', 'C175'), Campo(2, 'IND_VEIC_OPER'), - Campo(3, 'CNPJ'), + CampoCNPJ(3, 'CNPJ'), Campo(4, 'UF'), Campo(5, 'CHASSI_VEIC'), ] + nivel = 4 class RegistroC176(Registro): """ - RESSARCIMENTO DE ICMS EM OPERAÇÕES COM SUBSTITUIÇÃO TRIBUTÁRIA (CÓDIGO 01 E 55) + RESSARCIMENTO DE ICMS E FUNDO DE COMBATE À POBREZA + (FCP) EM OPERAÇÕES COM SUBSTITUIÇÃO TRIBUTÁRIA (CÓDIGO 01, 55) """ campos = [ CampoFixo(1, 'REG', 'C176'), Campo(2, 'COD_MOD_ULT_E'), - Campo(3, 'NUM_DOC_ULT_E'), + CampoNumerico(3, 'NUM_DOC_ULT_E'), Campo(4, 'SER_ULT_E'), - Campo(5, 'DT_ULT_E'), + CampoData(5, 'DT_ULT_E'), Campo(6, 'COD_PART_ULT_E'), - Campo(7, 'QUANT_ULT_E'), - Campo(8, 'VL_UNIT_ULT_E'), - Campo(9, 'VL_UNIT_BC_ST'), - ] - + CampoNumerico(7, 'QUANT_ULT_E'), + CampoNumerico(8, 'VL_UNIT_ULT_E'), + CampoNumerico(9, 'VL_UNIT_BC_ST'), + CampoChaveEletronica(10, 'CHAVE_NFE_ULT_E'), + CampoNumerico(11, 'NUM_ITEM_ULT_E'), + CampoNumerico(12, 'VL_UNIT_BC_ICMS_ULT_E'), + CampoNumerico(13, 'ALIQ_ICMS_ULT_E'), + CampoNumerico(14, 'VL_UNIT_LIMITE_BC_ICMS_ULT_E'), + CampoNumerico(15, 'VL_UNIT_ICMS_ULT_E'), + CampoNumerico(16, 'ALIQ_ST_ULT_E'), + CampoNumerico(17, 'VL_UNIT_RES'), + CampoNumerico(18, 'COD_RESP_RET'), + CampoNumerico(19, 'COD_MOT_RES'), + CampoChaveEletronica(20, 'CHAVE_NFE_RET'), + Campo(21, 'COD_PART_NFE_RET'), + Campo(22, 'SER_NFE_RET'), + CampoNumerico(23, 'NUM_NFE_RET'), + CampoNumerico(24, 'ITEM_NFE_RET'), + Campo(25, 'COD_DA'), + Campo(26, 'NUM_DA'), + CampoNumerico(27, 'VL_UNIT_RES_FCP_ST'), + ] + + nivel = 4 class RegistroC177(Registro): """ @@ -721,7 +1003,8 @@ class RegistroC177(Registro): Campo(2, 'COD_SELO_IPI'), Campo(3, 'QT_SELO_IPI'), ] - + + nivel = 4 class RegistroC178(Registro): """ @@ -730,10 +1013,11 @@ class RegistroC178(Registro): campos = [ CampoFixo(1, 'REG', 'C178'), Campo(2, 'CL_ENQ'), - Campo(3, 'VL_UNID'), + CampoNumerico(3, 'VL_UNID'), Campo(4, 'QUANT_PAD'), ] + nivel = 4 class RegistroC179(Registro): """ @@ -748,6 +1032,56 @@ class RegistroC179(Registro): Campo(6, 'ICMS_RET'), ] + nivel = 4 + +class RegistroC180(Registro): + """ + INFORMAÇÕES COMPLEMENTARES DAS OPERAÇÕES DE ENTRADA + DE MERCADORIAS SUJEITAS À SUBSTITUIÇÃO TRIBUTÁRIA (CÓDIGO 01, 1B, 04 e 55) + """ + campos = [ + CampoFixo(1, 'REG', 'C180'), + CampoNumerico(2, 'COD_RESP_RET'), + CampoNumerico(3, 'QUANT_CONV'), + CampoNumerico(4, 'UNID'), + CampoNumerico(5, 'VL_UNIT_CONV'), + CampoNumerico(6, 'VL_UNIT_ICMS_OP_CONV'), + CampoNumerico(7, 'VL_UNIT_BC_ICMS_ST_CONV'), + CampoNumerico(8, 'VL_UNIT_ICMS_ST_CONV'), + CampoNumerico(9, 'VL_UNIT_FCP_ST_CONV'), + Campo(10, 'COD_DA'), + Campo(11, 'NUM_DA'), + ] + + nivel = 4 + +class RegistroC185(Registro): + """ + INFORMAÇÕES COMPLEMENTARES DAS OPERAÇÕES DE SAÍDA DE + MERCADORIAS SUJEITAS À SUBSTITUIÇÃO TRIBUTÁRIA (CÓDIGO 01, 1B, 04, 55 e 65). + """ + campos = [ + CampoFixo(1, 'REG', 'C185'), + CampoNumerico(2, 'NUM_ITEM'), + Campo(3, 'COD_ITEM'), + CampoNumerico(4, 'CST_ICMS'), + CampoNumerico(5, 'CFOP'), + Campo(6, 'COD_MOT_REST_COMPL'), + CampoNumerico(7, 'QUANT_CONV'), + CampoNumerico(8, 'UNID'), + CampoNumerico(9, 'VL_UNIT_CONV'), + CampoNumerico(10, 'VL_UNIT_ICMS_NA_OPERACAO_CONV'), + CampoNumerico(11, 'VL_UNIT_ICMS_OP_CONV'), + CampoNumerico(12, 'VL_UNIT_ICMS_OP_ESTOQUE_CONV'), + CampoNumerico(13, 'VL_UNIT_ICMS_ST_ESTOQUE_CONV'), + CampoNumerico(14, 'VL_UNIT_FCP_ICMS_ST_ESTOQUE_CONV'), + CampoNumerico(15, 'VL_UNIT_ICMS_ST_CONV_REST'), + CampoNumerico(16, 'VL_UNIT_FCP_ST_CONV_REST'), + CampoNumerico(17, 'VL_UNIT_ICMS_ST_CONV_COMPL'), + CampoNumerico(18, 'VL_UNIT_FCP_ST_CONV_COMPL'), + ] + + nivel = 3 class RegistroC190(Registro): """ @@ -755,19 +1089,33 @@ class RegistroC190(Registro): """ campos = [ CampoFixo(1, 'REG', 'C190'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_BC_ICMS_ST'), - Campo(9, 'VL_ICMS_ST'), - Campo(10, 'VL_RED_BC'), - Campo(11, 'VL_IPI'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_BC_ICMS_ST'), + CampoNumerico(9, 'VL_ICMS_ST'), + CampoNumerico(10, 'VL_RED_BC'), + CampoNumerico(11, 'VL_IPI'), Campo(12, 'COD_OBS'), ] + nivel = 3 + +class RegistroC191(Registro): + """ + INFORMAÇÕES DO FUNDO DE COMBATE À POBREZA – FCP – NA NFe (CÓDIGO 55) E NA NFC-E (CÓDIGO 65) + """ + campos = [ + CampoFixo(1, 'REG', 'C191'), + CampoNumerico(2, 'VL_FCP_OP'), + CampoNumerico(3, 'VL_FCP_ST'), + CampoNumerico(4, 'VL_FCP_RET'), + ] + + nivel = 4 class RegistroC195(Registro): """ @@ -779,6 +1127,7 @@ class RegistroC195(Registro): Campo(3, 'TXT_COMPL'), ] + nivel = 3 class RegistroC197(Registro): """ @@ -789,12 +1138,13 @@ class RegistroC197(Registro): Campo(2, 'COD_AJ'), Campo(3, 'DESCR_COMPL_AJ'), Campo(4, 'COD_ITEM'), - Campo(5, 'VL_BC_ICMS'), - Campo(6, 'ALIQ_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_OUTROS'), + CampoNumerico(5, 'VL_BC_ICMS'), + CampoNumerico(6, 'ALIQ_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_OUTROS'), ] + nivel = 4 class RegistroC300(Registro): """ @@ -804,16 +1154,17 @@ class RegistroC300(Registro): CampoFixo(1, 'REG', 'C300'), Campo(2, 'COD_MOD'), Campo(3, 'SER'), - Campo(4, 'SUB'), - Campo(5, 'NUM_DOC_INI'), - Campo(6, 'NUM_DOC_FIN'), - Campo(7, 'DT_DOC'), - Campo(8, 'VL_DOC'), - Campo(9, 'VL_PIS'), - Campo(10, 'VL_COFINS'), + CampoNumerico(4, 'SUB'), + CampoNumerico(5, 'NUM_DOC_INI'), + CampoNumerico(6, 'NUM_DOC_FIN'), + CampoData(7, 'DT_DOC'), + CampoNumerico(8, 'VL_DOC'), + CampoNumerico(9, 'VL_PIS'), + CampoNumerico(10, 'VL_COFINS'), Campo(11, 'COD_CTA'), ] + nivel = 2 class RegistroC310(Registro): """ @@ -821,9 +1172,10 @@ class RegistroC310(Registro): """ campos = [ CampoFixo(1, 'REG', 'C310'), - Campo(2, 'NUM_DOC_CANC'), + CampoNumerico(2, 'NUM_DOC_CANC'), ] + nivel = 3 class RegistroC320(Registro): """ @@ -831,16 +1183,17 @@ class RegistroC320(Registro): """ campos = [ CampoFixo(1, 'REG', 'C320'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_RED_BC'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_RED_BC'), Campo(9, 'COD_OBS'), ] + nivel = 3 class RegistroC321(Registro): """ @@ -849,16 +1202,17 @@ class RegistroC321(Registro): campos = [ CampoFixo(1, 'REG', 'C321'), Campo(2, 'COD_ITEM'), - Campo(3, 'QTD'), + CampoNumerico(3, 'QTD'), Campo(4, 'UNID'), - Campo(5, 'VL_ITEM'), - Campo(6, 'VL_DESC'), - Campo(7, 'VL_BC_ICMS'), - Campo(8, 'VL_ICMS'), - Campo(9, 'VL_PIS'), - Campo(10, 'VL_COFINS'), + CampoNumerico(5, 'VL_ITEM'), + CampoNumerico(6, 'VL_DESC'), + CampoNumerico(7, 'VL_BC_ICMS'), + CampoNumerico(8, 'VL_ICMS'), + CampoNumerico(9, 'VL_PIS'), + CampoNumerico(10, 'VL_COFINS'), ] + nivel = 4 class RegistroC350(Registro): """ @@ -868,16 +1222,17 @@ class RegistroC350(Registro): CampoFixo(1, 'REG', 'C350'), Campo(2, 'SER'), Campo(3, 'SUB_SER'), - Campo(4, 'NUM_DOC'), - Campo(5, 'DT_DOC'), - Campo(6, 'CNPJ_CPF'), - Campo(7, 'VL_MERC'), - Campo(8, 'VL_DOC'), - Campo(9, 'VL_DESC'), - Campo(10, 'VL_PIS'), - Campo(11, 'VL_COFINS'), + CampoNumerico(4, 'NUM_DOC'), + CampoData(5, 'DT_DOC'), + CampoCPFouCNPJ(6, 'CNPJ_CPF'), + CampoNumerico(7, 'VL_MERC'), + CampoNumerico(8, 'VL_DOC'), + CampoNumerico(9, 'VL_DESC'), + CampoNumerico(10, 'VL_PIS'), + CampoNumerico(11, 'VL_COFINS'), ] + nivel = 2 class RegistroC370(Registro): """ @@ -887,12 +1242,13 @@ class RegistroC370(Registro): CampoFixo(1, 'REG', 'C370'), Campo(2, 'NUM_ITEM'), Campo(3, 'COD_ITEM'), - Campo(4, 'QTD'), + CampoNumerico(4, 'QTD'), Campo(5, 'UNID'), - Campo(6, 'VL_ITEM'), - Campo(7, 'VL_DESC'), + CampoNumerico(6, 'VL_ITEM'), + CampoNumerico(7, 'VL_DESC'), ] + nivel = 3 class RegistroC390(Registro): """ @@ -900,16 +1256,17 @@ class RegistroC390(Registro): """ campos = [ CampoFixo(1, 'REG', 'C390'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_RED_BC'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_RED_BC'), Campo(9, 'COD_OBS'), ] + nivel = 3 class RegistroC400(Registro): """ @@ -923,6 +1280,7 @@ class RegistroC400(Registro): Campo(5, 'ECF_CX'), ] + nivel = 2 class RegistroC405(Registro): """ @@ -930,14 +1288,15 @@ class RegistroC405(Registro): """ campos = [ CampoFixo(1, 'REG', 'C405'), - Campo(2, 'DT_DOC'), + CampoData(2, 'DT_DOC'), Campo(3, 'CRO'), Campo(4, 'CRZ'), Campo(5, 'NUM_COO_FIN'), Campo(6, 'GT_FIN'), - Campo(7, 'VL_BRT'), + CampoNumerico(7, 'VL_BRT'), ] + nivel = 3 class RegistroC410(Registro): """ @@ -945,10 +1304,11 @@ class RegistroC410(Registro): """ campos = [ CampoFixo(1, 'REG', 'C410'), - Campo(2, 'VL_PIS'), - Campo(3, 'VL_COFINS'), + CampoNumerico(2, 'VL_PIS'), + CampoNumerico(3, 'VL_COFINS'), ] + nivel = 4 class RegistroC420(Registro): """ @@ -962,6 +1322,7 @@ class RegistroC420(Registro): Campo(5, 'DESCR_NR_TOT'), ] + nivel = 4 class RegistroC425(Registro): """ @@ -970,13 +1331,14 @@ class RegistroC425(Registro): campos = [ CampoFixo(1, 'REG', 'C425'), Campo(2, 'COD_ITEM'), - Campo(3, 'QTD'), + CampoNumerico(3, 'QTD'), Campo(4, 'UNID'), - Campo(5, 'VL_ITEM'), - Campo(6, 'VL_PIS'), - Campo(7, 'VL_COFINS'), + CampoNumerico(5, 'VL_ITEM'), + CampoNumerico(6, 'VL_PIS'), + CampoNumerico(7, 'VL_COFINS'), ] + nivel = 5 class RegistroC460(Registro): """ @@ -985,16 +1347,29 @@ class RegistroC460(Registro): campos = [ CampoFixo(1, 'REG', 'C460'), Campo(2, 'COD_MOD'), - Campo(3, 'COD_SIT'), - Campo(4, 'NUM_DOC'), - Campo(5, 'DT_DOC'), - Campo(6, 'VL_DOC'), - Campo(7, 'VL_PIS'), - Campo(8, 'VL_COFINS'), + CampoNumerico(3, 'COD_SIT'), + CampoNumerico(4, 'NUM_DOC'), + CampoData(5, 'DT_DOC'), + CampoNumerico(6, 'VL_DOC'), + CampoNumerico(7, 'VL_PIS'), + CampoNumerico(8, 'VL_COFINS'), Campo(9, 'CPF_CNPJ'), Campo(10, 'NOM_ADQ'), ] + nivel = 4 + +class RegistroC465(Registro): + """ + DOCUMENTO + """ + campos = [ + CampoFixo(1, 'REG', 'C465'), + CampoChaveEletronica(2, 'CHV_CFE'), + Campo(3, 'NUM_CCF'), + ] + + nivel = 5 class RegistroC470(Registro): """ @@ -1003,17 +1378,18 @@ class RegistroC470(Registro): campos = [ CampoFixo(1, 'REG', 'C470'), Campo(2, 'COD_ITEM'), - Campo(3, 'QTD'), - Campo(4, 'QTD_CANC'), + CampoNumerico(3, 'QTD'), + CampoNumerico(4, 'QTD_CANC'), Campo(5, 'UNID'), - Campo(6, 'VL_ITEM'), - Campo(7, 'CST_ICMS'), - Campo(8, 'CFOP'), - Campo(9, 'ALIQ_ICMS'), - Campo(10, 'VL_PIS'), - Campo(11, 'VL_COFINS'), + CampoNumerico(6, 'VL_ITEM'), + CampoNumerico(7, 'CST_ICMS'), + CampoNumerico(8, 'CFOP'), + CampoNumerico(9, 'ALIQ_ICMS'), + CampoNumerico(10, 'VL_PIS'), + CampoNumerico(11, 'VL_COFINS'), ] + nivel = 5 class RegistroC490(Registro): """ @@ -1021,15 +1397,16 @@ class RegistroC490(Registro): """ campos = [ CampoFixo(1, 'REG', 'C490'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), Campo(8, 'COD_OBS'), ] + nivel = 4 class RegistroC495(Registro): """ @@ -1037,22 +1414,23 @@ class RegistroC495(Registro): """ campos = [ CampoFixo(1, 'REG', 'C495'), - Campo(2, 'ALIQ_ICMS'), + CampoNumerico(2, 'ALIQ_ICMS'), Campo(3, 'COD_ITEM'), - Campo(4, 'QTD'), - Campo(5, 'QTD_CANC'), + CampoNumerico(4, 'QTD'), + CampoNumerico(5, 'QTD_CANC'), Campo(6, 'UNID'), - Campo(7, 'VL_ITEM'), - Campo(8, 'VL_DESC'), - Campo(9, 'VL_CANC'), - Campo(10, 'VL_ACMO'), - Campo(11, 'VL_BC_ICMS'), - Campo(12, 'VL_ICMS'), - Campo(13, 'VL_ISEN'), - Campo(14, 'VL_NT'), - Campo(15, 'VL_ICMS_ST'), + CampoNumerico(7, 'VL_ITEM'), + CampoNumerico(8, 'VL_DESC'), + CampoNumerico(9, 'VL_CANC'), + CampoNumerico(10, 'VL_ACMO'), + CampoNumerico(11, 'VL_BC_ICMS'), + CampoNumerico(12, 'VL_ICMS'), + CampoNumerico(13, 'VL_ISEN'), + CampoNumerico(14, 'VL_NT'), + CampoNumerico(15, 'VL_ICMS_ST'), ] + nivel = 2 class RegistroC500(Registro): """ @@ -1065,30 +1443,31 @@ class RegistroC500(Registro): Campo(3, 'IND_EMIT'), Campo(4, 'COD_PART'), Campo(5, 'COD_MOD'), - Campo(6, 'COD_SIT'), + CampoNumerico(6, 'COD_SIT'), Campo(7, 'SER'), - Campo(8, 'SUB'), + CampoNumerico(8, 'SUB'), Campo(9, 'COD_CONS'), - Campo(10, 'NUM_DOC'), - Campo(11, 'DT_DOC'), - Campo(12, 'DT_E_S'), - Campo(13, 'VL_DOC'), - Campo(14, 'VL_DESC'), - Campo(15, 'VL_FORN'), - Campo(16, 'VL_SERV_NT'), - Campo(17, 'VL_TERC'), - Campo(18, 'VL_DA'), - Campo(19, 'VL_BC_ICMS'), - Campo(20, 'VL_ICMS'), - Campo(21, 'VL_BC_ICMS_ST'), - Campo(22, 'VL_ICMS_ST'), + CampoNumerico(10, 'NUM_DOC'), + CampoData(11, 'DT_DOC'), + CampoData(12, 'DT_E_S'), + CampoNumerico(13, 'VL_DOC'), + CampoNumerico(14, 'VL_DESC'), + CampoNumerico(15, 'VL_FORN'), + CampoNumerico(16, 'VL_SERV_NT'), + CampoNumerico(17, 'VL_TERC'), + CampoNumerico(18, 'VL_DA'), + CampoNumerico(19, 'VL_BC_ICMS'), + CampoNumerico(20, 'VL_ICMS'), + CampoNumerico(21, 'VL_BC_ICMS_ST'), + CampoNumerico(22, 'VL_ICMS_ST'), Campo(23, 'COD_INF'), - Campo(24, 'VL_PIS'), - Campo(25, 'VL_COFINS'), + CampoNumerico(24, 'VL_PIS'), + CampoNumerico(25, 'VL_COFINS'), Campo(26, 'TP_LIGACAO'), Campo(27, 'COD_GRUPO_TENSAO'), ] + nivel = 2 class RegistroC510(Registro): """ @@ -1099,25 +1478,26 @@ class RegistroC510(Registro): Campo(2, 'NUM_ITEM'), Campo(3, 'COD_ITEM'), Campo(4, 'COD_CLASS'), - Campo(5, 'QTD'), + CampoNumerico(5, 'QTD'), Campo(6, 'UNID'), - Campo(7, 'VL_ITEM'), - Campo(8, 'VL_DESC'), - Campo(9, 'CST_ICMS'), - Campo(10, 'CFOP'), - Campo(11, 'VL_BC_ICMS'), - Campo(12, 'ALIQ_ICMS'), - Campo(13, 'VL_ICMS'), - Campo(14, 'VL_BC_ICMS_ST'), - Campo(15, 'ALIQ_ST'), - Campo(16, 'VL_ICMS_ST'), + CampoNumerico(7, 'VL_ITEM'), + CampoNumerico(8, 'VL_DESC'), + CampoNumerico(9, 'CST_ICMS'), + CampoNumerico(10, 'CFOP'), + CampoNumerico(11, 'VL_BC_ICMS'), + CampoNumerico(12, 'ALIQ_ICMS'), + CampoNumerico(13, 'VL_ICMS'), + CampoNumerico(14, 'VL_BC_ICMS_ST'), + CampoNumerico(15, 'ALIQ_ST'), + CampoNumerico(16, 'VL_ICMS_ST'), Campo(17, 'IND_REC'), Campo(18, 'COD_PART'), - Campo(19, 'VL_PIS'), - Campo(20, 'VL_COFINS'), + CampoNumerico(19, 'VL_PIS'), + CampoNumerico(20, 'VL_COFINS'), Campo(21, 'COD_CTA'), ] + nivel = 3 class RegistroC590(Registro): """ @@ -1126,18 +1506,19 @@ class RegistroC590(Registro): """ campos = [ CampoFixo(1, 'REG', 'C590'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_BC_ICMS_ST'), - Campo(9, 'VL_ICMS_ST'), - Campo(10, 'VL_RED_BC'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_BC_ICMS_ST'), + CampoNumerico(9, 'VL_ICMS_ST'), + CampoNumerico(10, 'VL_RED_BC'), Campo(11, 'COD_OBS'), ] + nivel = 3 class RegistroC600(Registro): """ @@ -1147,28 +1528,29 @@ class RegistroC600(Registro): campos = [ CampoFixo(1, 'REG', 'C600'), Campo(2, 'COD_MOD'), - Campo(3, 'COD_MUN'), + CampoNumerico(3, 'COD_MUN'), Campo(4, 'SER'), - Campo(5, 'SUB'), + CampoNumerico(5, 'SUB'), Campo(6, 'COD_CONS'), - Campo(7, 'QTD_CONS'), - Campo(8, 'QTD_CANC'), - Campo(9, 'DT_DOC'), - Campo(10, 'VL_DOC'), - Campo(11, 'VL_DESC'), + CampoNumerico(7, 'QTD_CONS'), + CampoNumerico(8, 'QTD_CANC'), + CampoData(9, 'DT_DOC'), + CampoNumerico(10, 'VL_DOC'), + CampoNumerico(11, 'VL_DESC'), Campo(12, 'CONS'), - Campo(13, 'VL_FORN'), - Campo(14, 'VL_SERV_NT'), - Campo(15, 'VL_TERC'), - Campo(16, 'VL_DA'), - Campo(17, 'VL_BC_ICMS'), - Campo(18, 'VL_ICMS'), - Campo(19, 'VL_BC_ICMS_ST'), - Campo(20, 'VL_ICMS_ST'), - Campo(21, 'VL_PIS'), - Campo(22, 'VL_COFINS'), + CampoNumerico(13, 'VL_FORN'), + CampoNumerico(14, 'VL_SERV_NT'), + CampoNumerico(15, 'VL_TERC'), + CampoNumerico(16, 'VL_DA'), + CampoNumerico(17, 'VL_BC_ICMS'), + CampoNumerico(18, 'VL_ICMS'), + CampoNumerico(19, 'VL_BC_ICMS_ST'), + CampoNumerico(20, 'VL_ICMS_ST'), + CampoNumerico(21, 'VL_PIS'), + CampoNumerico(22, 'VL_COFINS'), ] + nivel = 2 class RegistroC601(Registro): """ @@ -1177,9 +1559,10 @@ class RegistroC601(Registro): """ campos = [ CampoFixo(1, 'REG', 'C601'), - Campo(2, 'NUM_DOC_CANC'), + CampoNumerico(2, 'NUM_DOC_CANC'), ] + nivel = 3 class RegistroC610(Registro): """ @@ -1190,22 +1573,23 @@ class RegistroC610(Registro): CampoFixo(1, 'REG', 'C610'), Campo(2, 'COD_CLASS'), Campo(3, 'COD_ITEM'), - Campo(4, 'QTD'), + CampoNumerico(4, 'QTD'), Campo(5, 'UNID'), - Campo(6, 'VL_ITEM'), - Campo(7, 'VL_DESC'), - Campo(8, 'CST_ICMS'), - Campo(9, 'CFOP'), - Campo(10, 'ALIQ_ICMS'), - Campo(11, 'VL_BC_ICMS'), - Campo(12, 'VL_ICMS'), - Campo(13, 'VL_BC_ICMS_ST'), - Campo(14, 'VL_ICMS_ST'), - Campo(15, 'VL_PIS'), - Campo(16, 'VL_COFINS'), + CampoNumerico(6, 'VL_ITEM'), + CampoNumerico(7, 'VL_DESC'), + CampoNumerico(8, 'CST_ICMS'), + CampoNumerico(9, 'CFOP'), + CampoNumerico(10, 'ALIQ_ICMS'), + CampoNumerico(11, 'VL_BC_ICMS'), + CampoNumerico(12, 'VL_ICMS'), + CampoNumerico(13, 'VL_BC_ICMS_ST'), + CampoNumerico(14, 'VL_ICMS_ST'), + CampoNumerico(15, 'VL_PIS'), + CampoNumerico(16, 'VL_COFINS'), Campo(17, 'COD_CTA'), ] + nivel = 3 class RegistroC690(Registro): """ @@ -1214,18 +1598,19 @@ class RegistroC690(Registro): """ campos = [ CampoFixo(1, 'REG', 'C690'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_RED_BC'), - Campo(9, 'VL_BC_ICMS_ST'), - Campo(10, 'VL_ICMS_ST'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_RED_BC'), + CampoNumerico(9, 'VL_BC_ICMS_ST'), + CampoNumerico(10, 'VL_ICMS_ST'), Campo(11, 'COD_OBS'), ] + nivel = 3 class RegistroC700(Registro): """ @@ -1238,11 +1623,12 @@ class RegistroC700(Registro): Campo(3, 'SER'), Campo(4, 'NRO_ORD_INI'), Campo(5, 'NRO_ORD_FIN'), - Campo(6, 'DT_DOC_INI'), - Campo(7, 'DT_DOC_FIN'), + CampoData(6, 'DT_DOC_INI'), + CampoData(7, 'DT_DOC_FIN'), Campo(8, 'NOM_MEST'), ] + nivel = 2 class RegistroC790(Registro): """ @@ -1250,18 +1636,19 @@ class RegistroC790(Registro): """ campos = [ CampoFixo(1, 'REG', 'C790'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_BC_ICMS_ST'), - Campo(9, 'VL_ICMS_ST'), - Campo(10, 'VL_RED_BC'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_BC_ICMS_ST'), + CampoNumerico(9, 'VL_ICMS_ST'), + CampoNumerico(10, 'VL_RED_BC'), Campo(11, 'COD_OBS'), ] + nivel = 3 class RegistroC791(Registro): """ @@ -1270,10 +1657,11 @@ class RegistroC791(Registro): campos = [ CampoFixo(1, 'REG', 'C791'), Campo(2, 'UF'), - Campo(3, 'VL_BC_ICMS_ST'), - Campo(4, 'VL_ICMS_ST'), + CampoNumerico(3, 'VL_BC_ICMS_ST'), + CampoNumerico(4, 'VL_ICMS_ST'), ] + nivel = 4 class RegistroC800(Registro): """ @@ -1282,23 +1670,24 @@ class RegistroC800(Registro): campos = [ CampoFixo(1, 'REG', 'C800'), Campo(2, 'COD_MOD'), - Campo(3, 'COD_SIT'), - Campo(4, 'NUM_CFE'), - Campo(5, 'DT_DOC'), - Campo(6, 'VL_CFE'), - Campo(7, 'VL_PIS'), - Campo(8, 'VL_COFINS'), - Campo(9, 'CNPJ_CPF'), - Campo(10, 'NR_SAT'), - Campo(11, 'CHV_CFE'), - Campo(12, 'VL_DESC'), - Campo(13, 'VL_MERC'), - Campo(14, 'VL_OUT_DA'), - Campo(15, 'VL_ICMS'), - Campo(16, 'VL_PIS_ST'), - Campo(17, 'VL_COFINS_ST'), + CampoNumerico(3, 'COD_SIT'), + CampoNumerico(4, 'NUM_CFE'), + CampoData(5, 'DT_DOC'), + CampoNumerico(6, 'VL_CFE'), + CampoNumerico(7, 'VL_PIS'), + CampoNumerico(8, 'VL_COFINS'), + CampoCPFouCNPJ(9, 'CNPJ_CPF'), + CampoNumerico(10, 'NR_SAT'), + CampoChaveEletronica(11, 'CHV_CFE'), + CampoNumerico(12, 'VL_DESC'), + CampoNumerico(13, 'VL_MERC'), + CampoNumerico(14, 'VL_OUT_DA'), + CampoNumerico(15, 'VL_ICMS'), + CampoNumerico(16, 'VL_PIS_ST'), + CampoNumerico(17, 'VL_COFINS_ST'), ] + nivel = 2 class RegistroC850(Registro): """ @@ -1306,15 +1695,16 @@ class RegistroC850(Registro): """ campos = [ CampoFixo(1, 'REG', 'C850'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), Campo(8, 'COD_OBS'), ] + nivel = 3 class RegistroC860(Registro): """ @@ -1323,12 +1713,13 @@ class RegistroC860(Registro): campos = [ CampoFixo(1, 'REG', 'C860'), Campo(2, 'COD_MOD'), - Campo(3, 'NR_SAT'), - Campo(4, 'DT_DOC'), + CampoNumerico(3, 'NR_SAT'), + CampoData(4, 'DT_DOC'), Campo(5, 'DOC_INI'), Campo(6, 'DOC_FIM'), ] + nivel = 2 class RegistroC890(Registro): """ @@ -1336,15 +1727,16 @@ class RegistroC890(Registro): """ campos = [ CampoFixo(1, 'REG', 'C890'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), Campo(8, 'COD_OBS'), ] + nivel = 3 class RegistroC990(Registro): """ @@ -1355,6 +1747,7 @@ class RegistroC990(Registro): CampoNumerico(2, 'QTD_LIN_C'), ] + nivel = 1 class RegistroD001(Registro): """ @@ -1365,6 +1758,7 @@ class RegistroD001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class RegistroD100(Registro): """ @@ -1379,28 +1773,44 @@ class RegistroD100(Registro): Campo(3, 'IND_EMIT'), Campo(4, 'COD_PART'), Campo(5, 'COD_MOD'), - Campo(6, 'COD_SIT'), + CampoNumerico(6, 'COD_SIT'), Campo(7, 'SER'), - Campo(8, 'SUB'), - Campo(9, 'NUM_DOC'), - Campo(10, 'CHV_CTE'), - Campo(11, 'DT_DOC'), - Campo(12, 'DT_A_P'), + CampoNumerico(8, 'SUB'), + CampoNumerico(9, 'NUM_DOC'), + CampoChaveEletronica(10, 'CHV_CTE'), + CampoData(11, 'DT_DOC'), + CampoData(12, 'DT_A_P'), Campo(13, 'TP_CT-e'), - Campo(14, 'CHV_CTE_REF'), - Campo(15, 'VL_DOC'), - Campo(16, 'VL_DESC'), + CampoChaveEletronica(14, 'CHV_CTE_REF'), + CampoNumerico(15, 'VL_DOC'), + CampoNumerico(16, 'VL_DESC'), Campo(17, 'IND_FRT'), - Campo(18, 'VL_SERV'), - Campo(19, 'VL_BC_ICMS'), - Campo(20, 'VL_ICMS'), - Campo(21, 'VL_NT'), + CampoNumerico(18, 'VL_SERV'), + CampoNumerico(19, 'VL_BC_ICMS'), + CampoNumerico(20, 'VL_ICMS'), + CampoNumerico(21, 'VL_NT'), Campo(22, 'COD_INF'), Campo(23, 'COD_CTA'), - Campo(24, 'COD_MUN_ORIG'), - Campo(25, 'COD_MUN_DEST'), + CampoNumerico(24, 'COD_MUN_ORIG'), + CampoNumerico(25, 'COD_MUN_DEST'), ] + nivel = 2 + +class RegistroD101(Registro): + """ + INFORMAÇÃO COMPLEMENTAR DOS DOCUMENTOS FISCAIS + QUANDO DAS PRESTAÇÕES INTERESTADUAIS DESTINADAS A CONSUMIDOR FINAL + NÃO CONTRIBUINTE EC 87/15 (CÓDIGOS 57, 63 e 67) + """ + campos = [ + CampoFixo(1, 'REG', 'D101'), + CampoNumerico(2, 'VL_FCP_UF_DEST'), + CampoNumerico(3, 'VL_ICMS_UF_DEST'), + CampoNumerico(4, 'VL_ICMS_UF_REM'), + ] + + nivel = 3 class RegistroD110(Registro): """ @@ -1410,10 +1820,11 @@ class RegistroD110(Registro): CampoFixo(1, 'REG', 'D110'), Campo(2, 'NUM_ITEM'), Campo(3, 'COD_ITEM'), - Campo(4, 'VL_SERV'), - Campo(5, 'VL_OUT'), + CampoNumerico(4, 'VL_SERV'), + CampoNumerico(5, 'VL_OUT'), ] + nivel = 3 class RegistroD120(Registro): """ @@ -1421,12 +1832,13 @@ class RegistroD120(Registro): """ campos = [ CampoFixo(1, 'REG', 'D120'), - Campo(2, 'COD_MUN_ORIG'), - Campo(3, 'COD_MUN_DEST'), + CampoNumerico(2, 'COD_MUN_ORIG'), + CampoNumerico(3, 'COD_MUN_DEST'), Campo(4, 'VEIC_ID'), Campo(5, 'UF_ID'), ] + nivel = 4 class RegistroD130(Registro): """ @@ -1437,18 +1849,19 @@ class RegistroD130(Registro): Campo(2, 'COD_PART_CONSG'), Campo(3, 'COD_PART_RED'), Campo(4, 'IND_FRT_RED'), - Campo(5, 'COD_MUN_ORIG'), - Campo(6, 'COD_MUN_DEST'), + CampoNumerico(5, 'COD_MUN_ORIG'), + CampoNumerico(6, 'COD_MUN_DEST'), Campo(7, 'VEIC_ID'), - Campo(8, 'VL_LIQ_FRT'), - Campo(9, 'VL_SEC_CAT'), - Campo(10, 'VL_DESP'), - Campo(11, 'VL_PEDG'), - Campo(12, 'VL_OUT'), - Campo(13, 'VL_FRT'), + CampoNumerico(8, 'VL_LIQ_FRT'), + CampoNumerico(9, 'VL_SEC_CAT'), + CampoNumerico(10, 'VL_DESP'), + CampoNumerico(11, 'VL_PEDG'), + CampoNumerico(12, 'VL_OUT'), + CampoNumerico(13, 'VL_FRT'), Campo(14, 'UF_ID'), ] + nivel = 3 class RegistroD140(Registro): """ @@ -1457,20 +1870,21 @@ class RegistroD140(Registro): campos = [ CampoFixo(1, 'REG', 'D140'), Campo(2, 'COD_PART_CONSG'), - Campo(3, 'COD_MUN_ORIG'), - Campo(4, 'COD_MUN_DEST'), + CampoNumerico(3, 'COD_MUN_ORIG'), + CampoNumerico(4, 'COD_MUN_DEST'), Campo(5, 'IND_VEIC'), Campo(6, 'VEIC_ID'), Campo(7, 'IND_NAV'), Campo(8, 'VIAGEM'), - Campo(9, 'VL_FRT_LIQ'), - Campo(10, 'VL_DESP_PORT'), - Campo(11, 'VL_DESP_CAR_DESC'), - Campo(12, 'VL_OUT'), - Campo(13, 'VL_FRT_BRT'), - Campo(14, 'VL_FRT_MM'), + CampoNumerico(9, 'VL_FRT_LIQ'), + CampoNumerico(10, 'VL_DESP_PORT'), + CampoNumerico(11, 'VL_DESP_CAR_DESC'), + CampoNumerico(12, 'VL_OUT'), + CampoNumerico(13, 'VL_FRT_BRT'), + CampoNumerico(14, 'VL_FRT_MM'), ] + nivel = 3 class RegistroD150(Registro): """ @@ -1478,18 +1892,19 @@ class RegistroD150(Registro): """ campos = [ CampoFixo(1, 'REG', 'D150'), - Campo(2, 'COD_MUN_ORIG'), - Campo(3, 'COD_MUN_DEST'), + CampoNumerico(2, 'COD_MUN_ORIG'), + CampoNumerico(3, 'COD_MUN_DEST'), Campo(4, 'VEIC_ID'), Campo(5, 'VIAGEM'), Campo(6, 'IND_TFA'), - Campo(7, 'VL_PESO_TX'), - Campo(8, 'VL_TX_TERR'), - Campo(9, 'VL_TX_RED'), - Campo(10, 'VL_OUT'), - Campo(11, 'VL_TX_ADV'), + CampoNumerico(7, 'VL_PESO_TX'), + CampoNumerico(8, 'VL_TX_TERR'), + CampoNumerico(9, 'VL_TX_RED'), + CampoNumerico(10, 'VL_OUT'), + CampoNumerico(11, 'VL_TX_ADV'), ] + nivel = 3 class RegistroD160(Registro): """ @@ -1498,14 +1913,15 @@ class RegistroD160(Registro): campos = [ CampoFixo(1, 'REG', 'D160'), Campo(2, 'DESPACHO'), - Campo(3, 'CNPJ_CPF_REM'), + CampoCPFouCNPJ(3, 'CNPJ_CPF_REM'), Campo(4, 'IE_REM'), - Campo(5, 'COD_MUN_ORI'), - Campo(6, 'CNPJ_CPF_DEST'), + CampoNumerico(5, 'COD_MUN_ORI'), + CampoCPFouCNPJ(6, 'CNPJ_CPF_DEST'), Campo(7, 'IE_DEST'), - Campo(8, 'COD_MUN_DEST'), + CampoNumerico(8, 'COD_MUN_DEST'), ] + nivel = 3 class RegistroD161(Registro): """ @@ -1514,14 +1930,15 @@ class RegistroD161(Registro): campos = [ CampoFixo(1, 'REG', 'D161'), Campo(2, 'IND_CARGA'), - Campo(3, 'CNPJ_CPF_COL'), + CampoCPFouCNPJ(3, 'CNPJ_CPF_COL'), Campo(4, 'IE_COL'), - Campo(5, 'COD_MUN_COL'), - Campo(6, 'CNPJ_CPF_ENTG'), + CampoNumerico(5, 'COD_MUN_COL'), + CampoCPFouCNPJ(6, 'CNPJ_CPF_ENTG'), Campo(7, 'IE_ENTG'), - Campo(8, 'COD_MUN_ENTG'), + CampoNumerico(8, 'COD_MUN_ENTG'), ] + nivel = 4 class RegistroD162(Registro): """ @@ -1531,15 +1948,16 @@ class RegistroD162(Registro): CampoFixo(1, 'REG', 'D162'), Campo(2, 'COD_MOD'), Campo(3, 'SER'), - Campo(4, 'NUM_DOC'), - Campo(5, 'DT_DOC'), - Campo(6, 'VL_DOC'), - Campo(7, 'VL_MERC'), - Campo(8, 'QTD_VOL'), - Campo(9, 'PESO_BRT'), - Campo(10, 'PESO_LIQ'), + CampoNumerico(4, 'NUM_DOC'), + CampoData(5, 'DT_DOC'), + CampoNumerico(6, 'VL_DOC'), + CampoNumerico(7, 'VL_MERC'), + CampoNumerico(8, 'QTD_VOL'), + CampoNumerico(9, 'PESO_BRT'), + CampoNumerico(10, 'PESO_LIQ'), ] + nivel = 4 class RegistroD170(Registro): """ @@ -1549,19 +1967,20 @@ class RegistroD170(Registro): CampoFixo(1, 'REG', 'D170'), Campo(2, 'COD_PART_CONSG'), Campo(3, 'COD_PART_RED'), - Campo(4, 'COD_MUN_ORIG'), - Campo(5, 'COD_MUN_DEST'), + CampoNumerico(4, 'COD_MUN_ORIG'), + CampoNumerico(5, 'COD_MUN_DEST'), Campo(6, 'OTM'), Campo(7, 'IND_NAT_FRT'), - Campo(8, 'VL_LIQ_FRT'), - Campo(9, 'VL_GRIS'), - Campo(10, 'VL_PDG'), - Campo(11, 'VL_OUT'), - Campo(12, 'VL_FRT'), + CampoNumerico(8, 'VL_LIQ_FRT'), + CampoNumerico(9, 'VL_GRIS'), + CampoNumerico(10, 'VL_PDG'), + CampoNumerico(11, 'VL_OUT'), + CampoNumerico(12, 'VL_FRT'), Campo(13, 'VEIC_ID'), Campo(14, 'UF_ID'), ] + nivel = 3 class RegistroD180(Registro): """ @@ -1571,22 +1990,23 @@ class RegistroD180(Registro): CampoFixo(1, 'REG', 'D180'), Campo(2, 'NUM_SEQ'), Campo(3, 'IND_EMIT'), - Campo(4, 'CNPJ_CPF_EMIT'), + CampoCPFouCNPJ(4, 'CNPJ_CPF_EMIT'), Campo(5, 'UF_EMIT'), Campo(6, 'IE_EMIT'), - Campo(7, 'COD_MUN_ORIG'), - Campo(8, 'CNPJ_CPF_TOM'), + CampoNumerico(7, 'COD_MUN_ORIG'), + CampoCPFouCNPJ(8, 'CNPJ_CPF_TOM'), Campo(9, 'UF_TOM'), Campo(10, 'IE_TOM'), - Campo(11, 'COD_MUN_DEST'), + CampoNumerico(11, 'COD_MUN_DEST'), Campo(12, 'COD_MOD'), Campo(13, 'SER'), - Campo(14, 'SUB'), - Campo(15, 'NUM_DOC'), - Campo(16, 'DT_DOC'), - Campo(17, 'VL_DOC'), + CampoNumerico(14, 'SUB'), + CampoNumerico(15, 'NUM_DOC'), + CampoData(16, 'DT_DOC'), + CampoNumerico(17, 'VL_DOC'), ] + nivel = 3 class RegistroD190(Registro): """ @@ -1594,16 +2014,17 @@ class RegistroD190(Registro): """ campos = [ CampoFixo(1, 'REG', 'D190'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_RED_BC'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_RED_BC'), Campo(9, 'COD_OBS'), ] - + + nivel = 3 class RegistroD195(Registro): """ @@ -1615,6 +2036,7 @@ class RegistroD195(Registro): Campo(3, 'TXT_COMPL'), ] + nivel = 3 class RegistroD197(Registro): """ @@ -1625,12 +2047,13 @@ class RegistroD197(Registro): Campo(2, 'COD_AJ'), Campo(3, 'DESCR_COMPL_AJ'), Campo(4, 'COD_ITEM'), - Campo(5, 'VL_BC_ICMS'), - Campo(6, 'ALIQ_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_OUTROS'), + CampoNumerico(5, 'VL_BC_ICMS'), + CampoNumerico(6, 'ALIQ_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_OUTROS'), ] + nivel = 4 class RegistroD300(Registro): """ @@ -1641,25 +2064,26 @@ class RegistroD300(Registro): CampoFixo(1, 'REG', 'D300'), Campo(2, 'COD_MOD'), Campo(3, 'SER'), - Campo(4, 'SUB'), - Campo(5, 'NUM_DOC_INI'), - Campo(6, 'NUM_DOC_FIN'), - Campo(7, 'CST_ICMS'), - Campo(8, 'CFOP'), - Campo(9, 'ALIQ_ICMS'), - Campo(10, 'DT_DOC'), - Campo(11, 'VL_OPR'), - Campo(12, 'VL_DESC'), - Campo(13, 'VL_SERV'), - Campo(14, 'VL_SEG'), - Campo(15, 'VL_OUT DESP'), - Campo(16, 'VL_BC_ICMS'), - Campo(17, 'VL_ICMS'), - Campo(18, 'VL_RED_BC'), + CampoNumerico(4, 'SUB'), + CampoNumerico(5, 'NUM_DOC_INI'), + CampoNumerico(6, 'NUM_DOC_FIN'), + CampoNumerico(7, 'CST_ICMS'), + CampoNumerico(8, 'CFOP'), + CampoNumerico(9, 'ALIQ_ICMS'), + CampoData(10, 'DT_DOC'), + CampoNumerico(11, 'VL_OPR'), + CampoNumerico(12, 'VL_DESC'), + CampoNumerico(13, 'VL_SERV'), + CampoNumerico(14, 'VL_SEG'), + CampoNumerico(15, 'VL_OUT DESP'), + CampoNumerico(16, 'VL_BC_ICMS'), + CampoNumerico(17, 'VL_ICMS'), + CampoNumerico(18, 'VL_RED_BC'), Campo(19, 'COD_OBS'), Campo(20, 'COD_CTA'), ] + nivel = 2 class RegistroD301(Registro): """ @@ -1668,9 +2092,10 @@ class RegistroD301(Registro): """ campos = [ CampoFixo(1, 'REG', 'D301'), - Campo(2, 'NUM_DOC_CANC'), + CampoNumerico(2, 'NUM_DOC_CANC'), ] + nivel = 3 class RegistroD310(Registro): """ @@ -1678,12 +2103,13 @@ class RegistroD310(Registro): """ campos = [ CampoFixo(1, 'REG', 'D310'), - Campo(2, 'COD_MUN_ORIG'), - Campo(3, 'VL_SERV'), - Campo(4, 'VL_BC_ICMS'), - Campo(5, 'VL_ICMS'), + CampoNumerico(2, 'COD_MUN_ORIG'), + CampoNumerico(3, 'VL_SERV'), + CampoNumerico(4, 'VL_BC_ICMS'), + CampoNumerico(5, 'VL_ICMS'), ] + nivel = 3 class RegistroD350(Registro): """ @@ -1697,6 +2123,7 @@ class RegistroD350(Registro): Campo(5, 'ECF_CX'), ] + nivel = 2 class RegistroD355(Registro): """ @@ -1704,14 +2131,15 @@ class RegistroD355(Registro): """ campos = [ CampoFixo(1, 'REG', 'D355'), - Campo(2, 'DT_DOC'), + CampoData(2, 'DT_DOC'), Campo(3, 'CRO'), Campo(4, 'CRZ'), Campo(5, 'NUM_COO_FIN'), Campo(6, 'GT_FIN'), - Campo(7, 'VL_BRT'), + CampoNumerico(7, 'VL_BRT'), ] + nivel = 3 class RegistroD360(Registro): """ @@ -1719,10 +2147,11 @@ class RegistroD360(Registro): """ campos = [ CampoFixo(1, 'REG', 'D360'), - Campo(2, 'VL_PIS'), - Campo(3, 'VL_COFINS'), + CampoNumerico(2, 'VL_PIS'), + CampoNumerico(3, 'VL_COFINS'), ] + nivel = 4 class RegistroD365(Registro): """ @@ -1736,6 +2165,7 @@ class RegistroD365(Registro): Campo(5, 'DESCR_NR_TOT'), ] + nivel = 4 class RegistroD370(Registro): """ @@ -1743,13 +2173,14 @@ class RegistroD370(Registro): """ campos = [ CampoFixo(1, 'REG', 'D370'), - Campo(2, 'COD_MUN_ORIG'), - Campo(3, 'VL_SERV'), - Campo(4, 'QTD_BILH'), - Campo(5, 'VL_BC_ICMS'), - Campo(6, 'VL_ICMS'), + CampoNumerico(2, 'COD_MUN_ORIG'), + CampoNumerico(3, 'VL_SERV'), + CampoNumerico(4, 'QTD_BILH'), + CampoNumerico(5, 'VL_BC_ICMS'), + CampoNumerico(6, 'VL_ICMS'), ] + nivel = 5 class RegistroD390(Registro): """ @@ -1757,18 +2188,19 @@ class RegistroD390(Registro): """ campos = [ CampoFixo(1, 'REG', 'D390'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ISSQN'), - Campo(7, 'ALIQ_ISSQN'), - Campo(8, 'VL_ISSQN'), - Campo(9, 'VL_BC_ICMS'), - Campo(10, 'VL_ICMS'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ISSQN'), + CampoNumerico(7, 'ALIQ_ISSQN'), + CampoNumerico(8, 'VL_ISSQN'), + CampoNumerico(9, 'VL_BC_ICMS'), + CampoNumerico(10, 'VL_ICMS'), Campo(11, 'COD_OBS'), ] + nivel = 4 class RegistroD400(Registro): """ @@ -1778,21 +2210,22 @@ class RegistroD400(Registro): CampoFixo(1, 'REG', 'D400'), Campo(2, 'COD_PART'), Campo(3, 'COD_MOD'), - Campo(4, 'COD_SIT'), + CampoNumerico(4, 'COD_SIT'), Campo(5, 'SER'), - Campo(6, 'SUB'), - Campo(7, 'NUM_DOC'), - Campo(8, 'DT_DOC'), - Campo(9, 'VL_DOC'), - Campo(10, 'VL_DESC'), - Campo(11, 'VL_SERV'), - Campo(12, 'VL_BC_ICMS'), - Campo(13, 'VL_ICMS'), - Campo(14, 'VL_PIS'), - Campo(15, 'VL_COFINS'), + CampoNumerico(6, 'SUB'), + CampoNumerico(7, 'NUM_DOC'), + CampoData(8, 'DT_DOC'), + CampoNumerico(9, 'VL_DOC'), + CampoNumerico(10, 'VL_DESC'), + CampoNumerico(11, 'VL_SERV'), + CampoNumerico(12, 'VL_BC_ICMS'), + CampoNumerico(13, 'VL_ICMS'), + CampoNumerico(14, 'VL_PIS'), + CampoNumerico(15, 'VL_COFINS'), Campo(16, 'COD_CTA'), ] + nivel = 2 class RegistroD410(Registro): """ @@ -1802,20 +2235,21 @@ class RegistroD410(Registro): CampoFixo(1, 'REG', 'D410'), Campo(2, 'COD_MOD'), Campo(3, 'SER'), - Campo(4, 'SUB'), - Campo(5, 'NUM_DOC_INI'), - Campo(6, 'NUM_DOC_FIN'), - Campo(7, 'DT_DOC'), - Campo(8, 'CST_ICMS'), - Campo(9, 'CFOP'), - Campo(10, 'ALIQ_ICMS'), - Campo(11, 'VL_OPR'), - Campo(12, 'VL_DESC'), - Campo(13, 'VL_SERV'), - Campo(14, 'VL_BC_ICMS'), - Campo(15, 'VL_ICMS'), + CampoNumerico(4, 'SUB'), + CampoNumerico(5, 'NUM_DOC_INI'), + CampoNumerico(6, 'NUM_DOC_FIN'), + CampoData(7, 'DT_DOC'), + CampoNumerico(8, 'CST_ICMS'), + CampoNumerico(9, 'CFOP'), + CampoNumerico(10, 'ALIQ_ICMS'), + CampoNumerico(11, 'VL_OPR'), + CampoNumerico(12, 'VL_DESC'), + CampoNumerico(13, 'VL_SERV'), + CampoNumerico(14, 'VL_BC_ICMS'), + CampoNumerico(15, 'VL_ICMS'), ] + nivel = 3 class RegistroD411(Registro): """ @@ -1823,9 +2257,10 @@ class RegistroD411(Registro): """ campos = [ CampoFixo(1, 'REG', 'D411'), - Campo(2, 'NUM_DOC_CANC'), + CampoNumerico(2, 'NUM_DOC_CANC'), ] + nivel = 4 class RegistroD420(Registro): """ @@ -1833,12 +2268,13 @@ class RegistroD420(Registro): """ campos = [ CampoFixo(1, 'REG', 'D420'), - Campo(2, 'COD_MUN_ORIG'), - Campo(3, 'VL_SERV'), - Campo(4, 'VL_BC_ICMS'), - Campo(5, 'VL_ICMS'), + CampoNumerico(2, 'COD_MUN_ORIG'), + CampoNumerico(3, 'VL_SERV'), + CampoNumerico(4, 'VL_BC_ICMS'), + CampoNumerico(5, 'VL_ICMS'), ] + nivel = 3 class RegistroD500(Registro): """ @@ -1850,27 +2286,28 @@ class RegistroD500(Registro): Campo(3, 'IND_EMIT'), Campo(4, 'COD_PART'), Campo(5, 'COD_MOD'), - Campo(6, 'COD_SIT'), + CampoNumerico(6, 'COD_SIT'), Campo(7, 'SER'), - Campo(8, 'SUB'), - Campo(9, 'NUM_DOC'), - Campo(10, 'DT_DOC'), - Campo(11, 'DT_A_P'), - Campo(12, 'VL_DOC'), - Campo(13, 'VL_DESC'), - Campo(14, 'VL_SERV'), - Campo(15, 'VL_SERV_NT'), - Campo(16, 'VL_TERC'), - Campo(17, 'VL_DA'), - Campo(18, 'VL_BC_ICMS'), - Campo(19, 'VL_ICMS'), + CampoNumerico(8, 'SUB'), + CampoNumerico(9, 'NUM_DOC'), + CampoData(10, 'DT_DOC'), + CampoData(11, 'DT_A_P'), + CampoNumerico(12, 'VL_DOC'), + CampoNumerico(13, 'VL_DESC'), + CampoNumerico(14, 'VL_SERV'), + CampoNumerico(15, 'VL_SERV_NT'), + CampoNumerico(16, 'VL_TERC'), + CampoNumerico(17, 'VL_DA'), + CampoNumerico(18, 'VL_BC_ICMS'), + CampoNumerico(19, 'VL_ICMS'), Campo(20, 'COD_INF'), - Campo(21, 'VL_PIS'), - Campo(22, 'VL_COFINS'), + CampoNumerico(21, 'VL_PIS'), + CampoNumerico(22, 'VL_COFINS'), Campo(23, 'COD_CTA'), Campo(24, 'TP_ASSINANTE'), ] + nivel = 2 class RegistroD510(Registro): """ @@ -1881,24 +2318,25 @@ class RegistroD510(Registro): Campo(2, 'NUM_ITEM'), Campo(3, 'COD_ITEM'), Campo(4, 'COD_CLASS'), - Campo(5, 'QTD'), + CampoNumerico(5, 'QTD'), Campo(6, 'UNID'), - Campo(7, 'VL_ITEM'), - Campo(8, 'VL_DESC'), - Campo(9, 'CST_ICMS'), - Campo(10, 'CFOP'), - Campo(11, 'VL_BC_ICMS'), - Campo(12, 'ALIQ_ICMS'), - Campo(13, 'VL_ICMS'), - Campo(14, 'VL_BC_ICMS_ST'), - Campo(15, 'VL_ICMS_ST'), + CampoNumerico(7, 'VL_ITEM'), + CampoNumerico(8, 'VL_DESC'), + CampoNumerico(9, 'CST_ICMS'), + CampoNumerico(10, 'CFOP'), + CampoNumerico(11, 'VL_BC_ICMS'), + CampoNumerico(12, 'ALIQ_ICMS'), + CampoNumerico(13, 'VL_ICMS'), + CampoNumerico(14, 'VL_BC_ICMS_ST'), + CampoNumerico(15, 'VL_ICMS_ST'), Campo(16, 'IND_REC'), Campo(17, 'COD_PART'), - Campo(18, 'VL_PIS'), - Campo(19, 'VL_COFINS'), + CampoNumerico(18, 'VL_PIS'), + CampoNumerico(19, 'VL_COFINS'), Campo(20, 'COD_CTA'), ] + nivel = 3 class RegistroD530(Registro): """ @@ -1907,13 +2345,14 @@ class RegistroD530(Registro): campos = [ CampoFixo(1, 'REG', 'D530'), Campo(2, 'IND_SERV'), - Campo(3, 'DT_INI_SERV'), - Campo(4, 'DT_FIN_SERV'), + CampoData(3, 'DT_INI_SERV'), + CampoData(4, 'DT_FIN_SERV'), Campo(5, 'PER_FISCAL'), Campo(6, 'COD_AREA'), Campo(7, 'TERMINAL'), ] + nivel = 3 class RegistroD590(Registro): """ @@ -1921,18 +2360,19 @@ class RegistroD590(Registro): """ campos = [ CampoFixo(1, 'REG', 'D590'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_BC_ICMS_ST'), - Campo(9, 'VL_ICMS_ST'), - Campo(10, 'VL_RED_BC'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_BC_ICMS_ST'), + CampoNumerico(9, 'VL_ICMS_ST'), + CampoNumerico(10, 'VL_RED_BC'), Campo(11, 'COD_OBS'), ] + nivel = 3 class RegistroD600(Registro): """ @@ -1942,24 +2382,25 @@ class RegistroD600(Registro): campos = [ CampoFixo(1, 'REG', 'D600'), Campo(2, 'COD_MOD'), - Campo(3, 'COD_MUN'), + CampoNumerico(3, 'COD_MUN'), Campo(4, 'SER'), - Campo(5, 'SUB'), + CampoNumerico(5, 'SUB'), Campo(6, 'COD_CONS'), - Campo(7, 'QTD_CONS'), - Campo(8, 'DT_DOC'), - Campo(9, 'VL_DOC'), - Campo(10, 'VL_DESC'), - Campo(11, 'VL_SERV'), - Campo(12, 'VL_SERV_N T'), - Campo(13, 'VL_TERC'), - Campo(14, 'VL_DA'), - Campo(15, 'VL_BC_ICMS'), - Campo(16, 'VL_ICMS'), - Campo(17, 'VL_PIS'), - Campo(18, 'VL_COFINS'), - ] - + CampoNumerico(7, 'QTD_CONS'), + CampoData(8, 'DT_DOC'), + CampoNumerico(9, 'VL_DOC'), + CampoNumerico(10, 'VL_DESC'), + CampoNumerico(11, 'VL_SERV'), + CampoNumerico(12, 'VL_SERV_N T'), + CampoNumerico(13, 'VL_TERC'), + CampoNumerico(14, 'VL_DA'), + CampoNumerico(15, 'VL_BC_ICMS'), + CampoNumerico(16, 'VL_ICMS'), + CampoNumerico(17, 'VL_PIS'), + CampoNumerico(18, 'VL_COFINS'), + ] + + nivel = 2 class RegistroD610(Registro): """ @@ -1969,23 +2410,24 @@ class RegistroD610(Registro): CampoFixo(1, 'REG', 'D610'), Campo(2, 'COD_CLASS'), Campo(3, 'COD_ITEM'), - Campo(4, 'QTD'), + CampoNumerico(4, 'QTD'), Campo(5, 'UNID'), - Campo(6, 'VL_ITEM'), - Campo(7, 'VL_DESC'), - Campo(8, 'CST_ICMS'), - Campo(9, 'CFOP'), - Campo(10, 'ALIQ_ICMS'), - Campo(11, 'VL_BC_ICMS'), - Campo(12, 'VL_ICMS'), - Campo(13, 'VL_BC_ICMS _ST'), - Campo(14, 'VL_ICMS_ST'), - Campo(15, 'VL_RED_BC'), - Campo(16, 'VL_PIS'), - Campo(17, 'VL_COFINS'), + CampoNumerico(6, 'VL_ITEM'), + CampoNumerico(7, 'VL_DESC'), + CampoNumerico(8, 'CST_ICMS'), + CampoNumerico(9, 'CFOP'), + CampoNumerico(10, 'ALIQ_ICMS'), + CampoNumerico(11, 'VL_BC_ICMS'), + CampoNumerico(12, 'VL_ICMS'), + CampoNumerico(13, 'VL_BC_ICMS _ST'), + CampoNumerico(14, 'VL_ICMS_ST'), + CampoNumerico(15, 'VL_RED_BC'), + CampoNumerico(16, 'VL_PIS'), + CampoNumerico(17, 'VL_COFINS'), Campo(18, 'COD_CTA'), ] + nivel = 3 class RegistroD690(Registro): """ @@ -1993,18 +2435,19 @@ class RegistroD690(Registro): """ campos = [ CampoFixo(1, 'REG', 'D690'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_BC_ICMS _ST'), - Campo(9, 'VL_ICMS_ST'), - Campo(10, 'VL_RED_BC'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_BC_ICMS _ST'), + CampoNumerico(9, 'VL_ICMS_ST'), + CampoNumerico(10, 'VL_RED_BC'), Campo(11, 'COD_OBS'), ] + nivel = 3 class RegistroD695(Registro): """ @@ -2017,11 +2460,12 @@ class RegistroD695(Registro): Campo(3, 'SER'), Campo(4, 'NRO_ORD_INI'), Campo(5, 'NRO_ORD_FIN'), - Campo(6, 'DT_DOC_INI'), - Campo(7, 'DT_DOC_FIN'), + CampoData(6, 'DT_DOC_INI'), + CampoData(7, 'DT_DOC_FIN'), Campo(8, 'NOM_MEST'), ] + nivel = 2 class RegistroD696(Registro): """ @@ -2029,18 +2473,19 @@ class RegistroD696(Registro): """ campos = [ CampoFixo(1, 'REG', 'D696'), - Campo(2, 'CST_ICMS'), - Campo(3, 'CFOP'), - Campo(4, 'ALIQ_ICMS'), - Campo(5, 'VL_OPR'), - Campo(6, 'VL_BC_ICMS'), - Campo(7, 'VL_ICMS'), - Campo(8, 'VL_BC_ICMS_ST'), - Campo(9, 'VL_ICMS_ST'), - Campo(10, 'VL_RED_BC'), + CampoNumerico(2, 'CST_ICMS'), + CampoNumerico(3, 'CFOP'), + CampoNumerico(4, 'ALIQ_ICMS'), + CampoNumerico(5, 'VL_OPR'), + CampoNumerico(6, 'VL_BC_ICMS'), + CampoNumerico(7, 'VL_ICMS'), + CampoNumerico(8, 'VL_BC_ICMS_ST'), + CampoNumerico(9, 'VL_ICMS_ST'), + CampoNumerico(10, 'VL_RED_BC'), Campo(11, 'COD_OBS'), ] + nivel = 3 class RegistroD697(Registro): """ @@ -2050,10 +2495,11 @@ class RegistroD697(Registro): campos = [ CampoFixo(1, 'REG', 'D697'), Campo(2, 'UF'), - Campo(3, 'VL_BC_ICMS'), - Campo(4, 'VL_ICMS'), + CampoNumerico(3, 'VL_BC_ICMS'), + CampoNumerico(4, 'VL_ICMS'), ] + nivel = 4 class RegistroD990(Registro): """ @@ -2064,6 +2510,7 @@ class RegistroD990(Registro): CampoNumerico(2, 'QTD_LIN_D'), ] + nivel = 1 class RegistroE001(Registro): """ @@ -2074,6 +2521,7 @@ class RegistroE001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class RegistroE100(Registro): """ @@ -2085,6 +2533,7 @@ class RegistroE100(Registro): CampoData(3, 'DT_FIN'), ] + nivel = 2 class RegistroE110(Registro): """ @@ -2092,22 +2541,23 @@ class RegistroE110(Registro): """ campos = [ CampoFixo(1, 'REG', 'E110'), - Campo(2, 'VL_TOT_DEBITOS'), - Campo(3, 'VL_AJ_DEBITOS'), - Campo(4, 'VL_TOT_AJ_DEBITOS'), - Campo(5, 'VL_ESTORNOS_CRED'), - Campo(6, 'VL_TOT_CREDITOS'), - Campo(7, 'VL_AJ_CREDITOS'), - Campo(8, 'VL_TOT_AJ_CREDITOS'), - Campo(9, 'VL_ESTORNOS_DEB'), - Campo(10, 'VL_SLD_CREDOR_ANT'), - Campo(11, 'VL_SLD_APURADO'), - Campo(12, 'VL_TOT_DED'), - Campo(13, 'VL_ICMS_RECOLHER'), - Campo(14, 'VL_SLD_CREDOR_TRANSPORTAR'), + CampoNumerico(2, 'VL_TOT_DEBITOS'), + CampoNumerico(3, 'VL_AJ_DEBITOS'), + CampoNumerico(4, 'VL_TOT_AJ_DEBITOS'), + CampoNumerico(5, 'VL_ESTORNOS_CRED'), + CampoNumerico(6, 'VL_TOT_CREDITOS'), + CampoNumerico(7, 'VL_AJ_CREDITOS'), + CampoNumerico(8, 'VL_TOT_AJ_CREDITOS'), + CampoNumerico(9, 'VL_ESTORNOS_DEB'), + CampoNumerico(10, 'VL_SLD_CREDOR_ANT'), + CampoNumerico(11, 'VL_SLD_APURADO'), + CampoNumerico(12, 'VL_TOT_DED'), + CampoNumerico(13, 'VL_ICMS_RECOLHER'), + CampoNumerico(14, 'VL_SLD_CREDOR_TRANSPORTAR'), Campo(15, 'DEB_ESP'), ] + nivel = 3 class RegistroE111(Registro): """ @@ -2117,9 +2567,10 @@ class RegistroE111(Registro): CampoFixo(1, 'REG', 'E111'), Campo(2, 'COD_AJ_APUR'), Campo(3, 'DESCR_COMPL_AJ'), - Campo(4, 'VL_AJ_APUR'), + CampoNumerico(4, 'VL_AJ_APUR'), ] + nivel = 4 class RegistroE112(Registro): """ @@ -2134,6 +2585,7 @@ class RegistroE112(Registro): Campo(6, 'TXT_COMPL'), ] + nivel = 5 class RegistroE113(Registro): """ @@ -2144,13 +2596,14 @@ class RegistroE113(Registro): Campo(2, 'COD_PART'), Campo(3, 'COD_MOD'), Campo(4, 'SER'), - Campo(5, 'SUB'), - Campo(6, 'NUM_DOC'), - Campo(7, 'DT_DOC'), + CampoNumerico(5, 'SUB'), + CampoNumerico(6, 'NUM_DOC'), + CampoData(7, 'DT_DOC'), Campo(8, 'COD_ITEM'), - Campo(9, 'VL_AJ_ITEM'), + CampoNumerico(9, 'VL_AJ_ITEM'), ] + nivel = 5 class RegistroE115(Registro): """ @@ -2159,10 +2612,11 @@ class RegistroE115(Registro): campos = [ CampoFixo(1, 'REG', 'E115'), Campo(2, 'COD_INF_ADIC'), - Campo(3, 'VL_INF_ADIC'), + CampoNumerico(3, 'VL_INF_ADIC'), Campo(4, 'DESCR_COMPL_AJ'), ] + nivel = 4 class RegistroE116(Registro): """ @@ -2171,8 +2625,8 @@ class RegistroE116(Registro): campos = [ CampoFixo(1, 'REG', 'E116'), Campo(2, 'COD_OR'), - Campo(3, 'VL_OR'), - Campo(4, 'DT_VCTO'), + CampoNumerico(3, 'VL_OR'), + CampoData(4, 'DT_VCTO'), Campo(5, 'COD_REC'), Campo(6, 'NUM_PROC'), Campo(7, 'IND_PROC'), @@ -2181,6 +2635,7 @@ class RegistroE116(Registro): Campo(10, 'MES_REF'), ] + nivel = 4 class RegistroE200(Registro): """ @@ -2192,7 +2647,8 @@ class RegistroE200(Registro): CampoData(3, 'DT_INI'), CampoData(4, 'DT_FIN'), ] - + + nivel = 2 class RegistroE210(Registro): """ @@ -2201,21 +2657,22 @@ class RegistroE210(Registro): campos = [ CampoFixo(1, 'REG', 'E210'), Campo(2, 'IND_MOV_ST'), - Campo(3, 'VL_SLD_CRED_ANT_ST'), - Campo(4, 'VL_DEVOL_ST'), - Campo(5, 'VL_RESSARC_ST'), - Campo(6, 'VL_OUT_CRED_ST'), - Campo(7, 'VL_AJ_CREDITOS_ST'), - Campo(8, 'VL_RETENÇAO_ST'), - Campo(9, 'VL_OUT_DEB_ST'), - Campo(10, 'VL_AJ_DEBITOS_ST'), - Campo(11, 'VL_SLD_DEV_ANT_ST'), - Campo(12, 'VL_DEDUÇÕES_ST'), - Campo(13, 'VL_ICMS_RECOL_ST'), - Campo(14, 'VL_SLD_CRED_ST_TRAN SPORTAR'), + CampoNumerico(3, 'VL_SLD_CRED_ANT_ST'), + CampoNumerico(4, 'VL_DEVOL_ST'), + CampoNumerico(5, 'VL_RESSARC_ST'), + CampoNumerico(6, 'VL_OUT_CRED_ST'), + CampoNumerico(7, 'VL_AJ_CREDITOS_ST'), + CampoNumerico(8, 'VL_RETENÇAO_ST'), + CampoNumerico(9, 'VL_OUT_DEB_ST'), + CampoNumerico(10, 'VL_AJ_DEBITOS_ST'), + CampoNumerico(11, 'VL_SLD_DEV_ANT_ST'), + CampoNumerico(12, 'VL_DEDUÇÕES_ST'), + CampoNumerico(13, 'VL_ICMS_RECOL_ST'), + CampoNumerico(14, 'VL_SLD_CRED_ST_TRAN SPORTAR'), Campo(15, 'DEB_ESP_ST'), ] + nivel = 3 class RegistroE220(Registro): """ @@ -2225,9 +2682,10 @@ class RegistroE220(Registro): CampoFixo(1, 'REG', 'E220'), Campo(2, 'COD_AJ_APUR'), Campo(3, 'DESCR_COMPL_AJ'), - Campo(4, 'VL_AJ_APUR'), + CampoNumerico(4, 'VL_AJ_APUR'), ] + nivel = 4 class RegistroE230(Registro): """ @@ -2242,6 +2700,7 @@ class RegistroE230(Registro): Campo(6, 'TXT_COMPL'), ] + nivel = 5 class RegistroE240(Registro): """ @@ -2253,13 +2712,14 @@ class RegistroE240(Registro): Campo(2, 'COD_PART'), Campo(3, 'COD_MOD'), Campo(4, 'SER'), - Campo(5, 'SUB'), - Campo(6, 'NUM_DOC'), - Campo(7, 'DT_DOC'), + CampoNumerico(5, 'SUB'), + CampoNumerico(6, 'NUM_DOC'), + CampoData(7, 'DT_DOC'), Campo(8, 'COD_ITEM'), - Campo(9, 'VL_AJ_ITEM'), + CampoNumerico(9, 'VL_AJ_ITEM'), ] + nivel = 5 class RegistroE250(Registro): """ @@ -2268,8 +2728,8 @@ class RegistroE250(Registro): campos = [ CampoFixo(1, 'REG', 'E250'), Campo(2, 'COD_OR'), - Campo(3, 'VL_OR'), - Campo(4, 'DT_VCTO'), + CampoNumerico(3, 'VL_OR'), + CampoData(4, 'DT_VCTO'), Campo(5, 'COD_REC'), Campo(6, 'NUM_PROC'), Campo(7, 'IND_PROC'), @@ -2278,6 +2738,7 @@ class RegistroE250(Registro): Campo(10, 'MES_REF'), ] + nivel = 4 class RegistroE300(Registro): """ @@ -2291,6 +2752,7 @@ class RegistroE300(Registro): CampoData(4, 'DT_FIN'), ] + nivel = 2 class RegistroE310(Registro): """ @@ -2301,28 +2763,83 @@ class RegistroE310(Registro): campos = [ CampoFixo(1, 'REG', 'E310'), Campo(2, 'IND_MOV_FCP_DIFAL'), - Campo(3, 'VL_SLD_CRED_ANT_DIFAL'), - Campo(4, 'VL_TOT_DEBITOS_DIFAL'), - Campo(5, 'VL_OUT_DEB_DIFAL'), - Campo(6, 'VL_TOT_CREDITOS_DIFAL'), - Campo(7, 'VL_OUT_CRED_DIFAL'), - Campo(8, 'VL_SLD_DEV_ANT_DIFAL'), - Campo(9, 'VL_DEDUCOES_DIFAL'), - Campo(10, 'VL_RECOL_DIFAL'), - Campo(11, 'VL_SLD_CRED_TRANSPORTAR_DIFAL'), + CampoNumerico(3, 'VL_SLD_CRED_ANT_DIFAL'), + CampoNumerico(4, 'VL_TOT_DEBITOS_DIFAL'), + CampoNumerico(5, 'VL_OUT_DEB_DIFAL'), + CampoNumerico(6, 'VL_TOT_CREDITOS_DIFAL'), + CampoNumerico(7, 'VL_OUT_CRED_DIFAL'), + CampoNumerico(8, 'VL_SLD_DEV_ANT_DIFAL'), + CampoNumerico(9, 'VL_DEDUCOES_DIFAL'), + CampoNumerico(10, 'VL_RECOL_DIFAL'), + CampoNumerico(11, 'VL_SLD_CRED_TRANSPORTAR_DIFAL'), Campo(12, 'DEB_ESP_DIFAL'), - Campo(13, 'VL_SLD_CRED_ANT_FCP'), - Campo(14, 'VL_TOT_DEB_FCP'), - Campo(15, 'VL_OUT_DEB_FCP'), - Campo(16, 'VL_TOT_CRED_FCP'), - Campo(17, 'VL_OUT_CRED_FCP'), - Campo(18, 'VL_SLD_DEV_ANT_FCP'), - Campo(19, 'VL_DEDUCOES_FCP'), - Campo(20, 'VL_RECOL_FCP'), - Campo(21, 'VL_SLD_CRED_TRANSPORTAR_FCP'), + CampoNumerico(13, 'VL_SLD_CRED_ANT_FCP'), + CampoNumerico(14, 'VL_TOT_DEB_FCP'), + CampoNumerico(15, 'VL_OUT_DEB_FCP'), + CampoNumerico(16, 'VL_TOT_CRED_FCP'), + CampoNumerico(17, 'VL_OUT_CRED_FCP'), + CampoNumerico(18, 'VL_SLD_DEV_ANT_FCP'), + CampoNumerico(19, 'VL_DEDUCOES_FCP'), + CampoNumerico(20, 'VL_RECOL_FCP'), + CampoNumerico(21, 'VL_SLD_CRED_TRANSPORTAR_FCP'), Campo(22, 'DEB_ESP_FCP'), ] + nivel = 3 + +class RegistroE311(Registro): + """ + AJUSTE/BENEFÍCIO/INCENTIVO DA APURAÇÃO DO FUNDO DE + COMBATE À POBREZA E DO ICMS DIFERENCIAL DE ALÍQUOTA UF + ORIGEM/DESTINO EC 87/15 + """ + campos = [ + CampoFixo(1, 'REG', 'E311'), + Campo(2, 'COD_AJ_APUR'), + Campo(3, 'DESCR_COMPL_AJ'), + CampoNumerico(4, 'VL_AJ_APUR'), + ] + + nivel = 4 + +class RegistroE312(Registro): + """ + REGISTRO E312: INFORMAÇÕES ADICIONAIS DOS AJUSTES DA APURAÇÃO DO + FUNDO DE COMBATE À POBREZA E DO ICMS DIFERENCIAL DE ALÍQUOTA UF + ORIGEM/DESTINO EC 87/15 + """ + campos = [ + CampoFixo(1, 'REG', 'E312'), + Campo(2, 'NUM_DA'), + Campo(3, 'NUM_PROC'), + Campo(4, 'IND_PROC'), + Campo(5, 'PROC'), + Campo(6, 'TXT_COMPL'), + ] + + nivel = 5 + +class RegistroE313(Registro): + """ + INFORMAÇÕES ADICIONAIS DOS AJUSTES DA APURAÇÃO DO + FUNDO DE COMBATE À POBREZA E DO ICMS DIFERENCIAL DE ALÍQUOTA UF + ORIGEM/DESTINO EC 87/15 - IDENTIFICAÇÃO DOS DOCUMENTOS FISCAIS + """ + campos = [ + CampoFixo(1, 'REG', 'E313'), + Campo(2, 'COD_PART'), + Campo(3, 'COD_MOD'), + Campo(4, 'SER'), + CampoNumerico(5, 'SUB'), + CampoNumerico(6, 'NUM_DOC'), + CampoChaveEletronica(7, 'CHV_DOCe'), + CampoData(8, 'DT_DOC'), + Campo(9, 'COD_ITEM'), + CampoNumerico(10, 'VL_AJ_ITEM'), + ] + + nivel = 5 + class RegistroE316(Registro): """ OBRIGAÇÕES RECOLHIDAS OU A RECOLHER – FUNDO DE @@ -2332,8 +2849,8 @@ class RegistroE316(Registro): campos = [ CampoFixo(1, 'REG', 'E316'), Campo(2, 'COD_OR'), - Campo(3, 'VL_OR'), - Campo(4, 'DT_VCTO'), + CampoNumerico(3, 'VL_OR'), + CampoData(4, 'DT_VCTO'), Campo(5, 'COD_REC'), Campo(6, 'NUM_PROC'), Campo(7, 'IND_PROC'), @@ -2342,6 +2859,7 @@ class RegistroE316(Registro): Campo(10, 'MES_REF'), ] + nivel = 4 class RegistroE500(Registro): """ @@ -2354,6 +2872,7 @@ class RegistroE500(Registro): CampoData(4, 'DT_FIN'), ] + nivel = 2 class RegistroE510(Registro): """ @@ -2361,13 +2880,14 @@ class RegistroE510(Registro): """ campos = [ CampoFixo(1, 'REG', 'E510'), - Campo(2, 'CFOP'), + CampoNumerico(2, 'CFOP'), Campo(3, 'CST_IPI'), - Campo(4, 'VL_CONT_IPI'), - Campo(5, 'VL_BC_IPI'), - Campo(6, 'VL_IPI'), + CampoNumerico(4, 'VL_CONT_IPI'), + CampoNumerico(5, 'VL_BC_IPI'), + CampoNumerico(6, 'VL_IPI'), ] + nivel = 3 class RegistroE520(Registro): """ @@ -2375,15 +2895,16 @@ class RegistroE520(Registro): """ campos = [ CampoFixo(1, 'REG', 'E520'), - Campo(2, 'VL_SD_ANT_IPI'), - Campo(3, 'VL_DEB_IPI'), - Campo(4, 'VL_CRED_IPI'), - Campo(5, 'VL_OD_IPI'), - Campo(6, 'VL_OC_IPI'), - Campo(7, 'VL_SC_IPI'), - Campo(8, 'VL_SD_IPI'), + CampoNumerico(2, 'VL_SD_ANT_IPI'), + CampoNumerico(3, 'VL_DEB_IPI'), + CampoNumerico(4, 'VL_CRED_IPI'), + CampoNumerico(5, 'VL_OD_IPI'), + CampoNumerico(6, 'VL_OC_IPI'), + CampoNumerico(7, 'VL_SC_IPI'), + CampoNumerico(8, 'VL_SD_IPI'), ] + nivel = 3 class RegistroE530(Registro): """ @@ -2392,13 +2913,34 @@ class RegistroE530(Registro): campos = [ CampoFixo(1, 'REG', 'E530'), Campo(2, 'IND_AJ'), - Campo(3, 'VL_AJ'), + CampoNumerico(3, 'VL_AJ'), Campo(4, 'COD_AJ'), Campo(5, 'IND_DOC'), - Campo(6, 'NUM_DOC'), + CampoNumerico(6, 'NUM_DOC'), Campo(7, 'DESCR_AJ'), ] + nivel = 4 + +class RegistroE531(Registro): + """ + INFORMAÇÕES ADICIONAIS DOS AJUSTES DA APURAÇÃO DO IPI – + IDENTIFICAÇÃO DOS DOCUMENTOS FISCAIS (01 e 55) + """ + campos = [ + CampoFixo(1, 'REG', 'E531'), + Campo(2, 'COD_PART'), + Campo(3, 'COD_MOD'), + Campo(4, 'SER'), + CampoNumerico(5, 'SUB'), + CampoNumerico(6, 'NUM_DOC'), + CampoData(7, 'DT_DOC'), + CampoNumerico(8, 'COD_ITEM'), + CampoNumerico(9, 'VL_AJ_ITEM'), + CampoChaveEletronica(10, 'CHV_NFE'), + ] + + nivel = 5 class RegistroE990(Registro): """ @@ -2409,6 +2951,7 @@ class RegistroE990(Registro): CampoNumerico(2, 'QTD_LIN_E'), ] + nivel = 1 class RegistroG001(Registro): """ @@ -2419,6 +2962,7 @@ class RegistroG001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class RegistroG110(Registro): """ @@ -2430,13 +2974,14 @@ class RegistroG110(Registro): CampoData(3, 'DT_FIN'), Campo(4, 'SALDO_IN_ICMS'), Campo(5, 'SOM_PARC'), - Campo(6, 'VL_TRIB_EXP'), - Campo(7, 'VL_TOTAL'), + CampoNumerico(6, 'VL_TRIB_EXP'), + CampoNumerico(7, 'VL_TOTAL'), Campo(8, 'IND_PER_SAI'), Campo(9, 'ICMS_APROP'), Campo(10, 'SOM_ICMS_OC'), ] + nivel = 2 class RegistroG125(Registro): """ @@ -2445,16 +2990,17 @@ class RegistroG125(Registro): campos = [ CampoFixo(1, 'REG', 'G125'), Campo(2, 'COD_IND_BEM'), - Campo(3, 'DT_MOV'), + CampoData(3, 'DT_MOV'), Campo(4, 'TIPO_MOV'), - Campo(5, 'VL_IMOB_ICMS_OP'), - Campo(6, 'VL_IMOB_ICMS_ST'), - Campo(7, 'VL_IMOB_ICMS_FRT'), - Campo(8, 'VL_IMOB_ICMS_DIF'), - Campo(9, 'NUM_PARC'), - Campo(10, 'VL_PARC_PASS'), + CampoNumerico(5, 'VL_IMOB_ICMS_OP'), + CampoNumerico(6, 'VL_IMOB_ICMS_ST'), + CampoNumerico(7, 'VL_IMOB_ICMS_FRT'), + CampoNumerico(8, 'VL_IMOB_ICMS_DIF'), + CampoNumerico(9, 'NUM_PARC'), + CampoNumerico(10, 'VL_PARC_PASS'), ] + nivel = 3 class RegistroG126(Registro): """ @@ -2464,14 +3010,15 @@ class RegistroG126(Registro): CampoFixo(1, 'REG', 'G126'), CampoData(2, 'DT_INI'), CampoData(3, 'DT_FIN'), - Campo(4, 'NUM_PARC'), - Campo(5, 'VL_PARC_PASS'), - Campo(6, 'VL_TRIB_OC'), - Campo(7, 'VL_TOTAL'), + CampoNumerico(4, 'NUM_PARC'), + CampoNumerico(5, 'VL_PARC_PASS'), + CampoNumerico(6, 'VL_TRIB_OC'), + CampoNumerico(7, 'VL_TOTAL'), Campo(8, 'IND_PER_SAI'), - Campo(9, 'VL_PARC_APRO P'), + CampoNumerico(9, 'VL_PARC_APRO P'), ] + nivel = 4 class RegistroG130(Registro): """ @@ -2483,11 +3030,12 @@ class RegistroG130(Registro): Campo(3, 'COD_PART'), Campo(4, 'COD_MOD'), Campo(5, 'SERIE'), - Campo(6, 'NUM_DOC'), - Campo(7, 'CHV_NFE_CTE'), - Campo(8, 'DT_DOC'), + CampoNumerico(6, 'NUM_DOC'), + CampoChaveEletronica(7, 'CHV_NFE_CTE'), + CampoData(8, 'DT_DOC'), ] + nivel = 4 class RegistroG140(Registro): """ @@ -2499,6 +3047,7 @@ class RegistroG140(Registro): Campo(3, 'COD_ITEM'), ] + nivel = 5 class RegistroG990(Registro): """ @@ -2509,6 +3058,7 @@ class RegistroG990(Registro): CampoNumerico(2, 'QTD_LIN_G'), ] + nivel = 1 class RegistroH001(Registro): """ @@ -2519,6 +3069,7 @@ class RegistroH001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class RegistroH005(Registro): """ @@ -2531,6 +3082,7 @@ class RegistroH005(Registro): Campo(4, 'MOT_INV'), ] + nivel = 2 class RegistroH010(Registro): """ @@ -2550,6 +3102,7 @@ class RegistroH010(Registro): CampoNumerico(11, 'VL_ITEM_IR'), ] + nivel = 3 class RegistroH020(Registro): """ @@ -2557,11 +3110,12 @@ class RegistroH020(Registro): """ campos = [ CampoFixo(1, 'REG', 'H020'), - Campo(2, 'CST_ICMS'), + CampoNumerico(2, 'CST_ICMS'), Campo(3, 'BC_ICMS'), - Campo(4, 'VL_ICMS'), + CampoNumerico(4, 'VL_ICMS'), ] + nivel = 4 class RegistroH990(Registro): """ @@ -2572,6 +3126,7 @@ class RegistroH990(Registro): CampoNumerico(2, 'QTD_LIN_H'), ] + nivel = 1 class RegistroK001(Registro): """ @@ -2582,6 +3137,7 @@ class RegistroK001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class RegistroK100(Registro): """ @@ -2593,6 +3149,7 @@ class RegistroK100(Registro): CampoData(3, 'DT_FIN'), ] + nivel = 2 class RegistroK200(Registro): """ @@ -2607,6 +3164,34 @@ class RegistroK200(Registro): Campo(6, 'COD_PART'), ] + nivel = 3 + +class RegistroK210(Registro): + """ + DESMONTAGEM DE MERCADORIAS – ITEM DE ORIGE + """ + campos = [ + CampoFixo(1, 'REG', 'K210'), + CampoData(2, 'DT_INI_OS'), + CampoData(3, 'DT_FIN_OS'), + Campo(4, 'COD_DOC_OS'), + Campo(5, 'COD_ITEM_ORI'), + CampoNumerico(6, 'QTD_ORI'), + ] + + nivel = 3 + +class RegistroK215(Registro): + """ + DESMONTAGEM DE MERCADORIAS – ITENS DE DESTINO + """ + campos = [ + CampoFixo(1, 'REG', 'K215'), + Campo(2, 'COD_ITEM_DES'), + CampoNumerico(3, 'QTD_DES'), + ] + + nivel = 4 class RegistroK220(Registro): """ @@ -2620,6 +3205,7 @@ class RegistroK220(Registro): CampoNumerico(5, 'QTD'), ] + nivel = 3 class RegistroK230(Registro): """ @@ -2634,6 +3220,7 @@ class RegistroK230(Registro): CampoNumerico(6, 'QTD_ENC'), ] + nivel = 3 class RegistroK235(Registro): """ @@ -2647,6 +3234,7 @@ class RegistroK235(Registro): Campo(5, 'COD_INS_SUBST'), ] + nivel = 4 class RegistroK250(Registro): """ @@ -2659,6 +3247,7 @@ class RegistroK250(Registro): CampoNumerico(4, 'QTD'), ] + nivel = 3 class RegistroK255(Registro): """ @@ -2672,6 +3261,161 @@ class RegistroK255(Registro): Campo(5, 'COD_INS_SUBST'), ] + nivel = 4 + +class RegistroK260(Registro): + """ + REPROCESSAMENTO/REPARO DE PRODUTO/INSUMO + """ + campos = [ + CampoFixo(1, 'REG', 'K260'), + Campo(2, 'OD_OP_OS'), + Campo(3, 'COD_ITEM'), + CampoData(4, 'DT_SAIDA'), + CampoNumerico(5, 'QTD_SAIDA'), + CampoData(6, 'DT_RET'), + CampoNumerico(7, 'QTD_RET'), + ] + + nivel = 3 + +class RegistroK265(Registro): + """ + REPROCESSAMENTO/REPARO – MERCADORIAS CONSUMIDAS E/OU + RETORNADAS + """ + campos = [ + CampoFixo(1, 'REG', 'K265'), + Campo(2, 'COD_ITEM'), + CampoNumerico(3, 'QTD_CONS'), + CampoNumerico(4, 'QTD_RET'), + ] + + nivel = 4 + +class RegistroK270(Registro): + """ + CORREÇÃO DE APONTAMENTO DOS REGISTROS K210, K220, K230, + K250, K260, K291, K292, K301 E K302 + """ + campos = [ + CampoFixo(1, 'REG', 'K270'), + CampoData(2, 'DT_INI_AP'), + CampoData(3, 'DT_FIN_AP'), + Campo(4, 'COD_OP_OS'), + Campo(5, 'COD_ITEM'), + CampoNumerico(6, 'QTD_COR_POS'), + CampoNumerico(7, 'QTD_COR_NEG'), + Campo(8, 'ORIGEM'), + ] + + nivel = 3 + +class RegistroK275(Registro): + """ + CORREÇÃO DE APONTAMENTO E RETORNO DE INSUMOS DOS + REGISTROS K215, K220, K235, K255 E K265. + """ + campos = [ + CampoFixo(1, 'REG', 'K275'), + Campo(2, 'COD_ITEM'), + CampoNumerico(3, 'QTD_COR_POS'), + CampoNumerico(4, 'QTD_COR_NEG'), + Campo(5, 'COD_INS_SUBST'), + ] + + nivel = 4 + +class RegistroK280(Registro): + """ + CORREÇÃO DE APONTAMENTO – ESTOQUE ESCRITURADO + """ + campos = [ + CampoFixo(1, 'REG', 'K280'), + CampoData(2, 'DT_EST'), + Campo(3, 'COD_ITEM'), + CampoNumerico(4, 'QTD_COR_POS'), + CampoNumerico(5, 'QTD_COR_NEG'), + Campo(6, 'IND_EST'), + Campo(7, 'COD_PART'), + ] + + nivel = 3 + +class RegistroK290(Registro): + """ + PRODUÇÃO CONJUNTA – ORDEM DE PRODUÇÃO + """ + campos = [ + CampoFixo(1, 'REG', 'K290'), + CampoData(2, 'DT_INI_OP'), + CampoData(3, 'DT_FIN_OP'), + Campo(4, 'COD_DOC_OP'), + ] + + nivel = 3 + +class RegistroK291(Registro): + """ + PRODUÇÃO CONJUNTA – ITENS PRODUZIDOS + """ + campos = [ + CampoFixo(1, 'REG', 'K291'), + Campo(2, 'COD_ITEM'), + CampoNumerico(3, 'QTD'), + ] + + nivel = 4 + +class RegistroK292(Registro): + """ + PRODUÇÃO CONJUNTA – INSUMOS CONSUMIDOS + """ + campos = [ + CampoFixo(1, 'REG', 'K292'), + Campo(2, 'COD_ITEM'), + CampoNumerico(3, 'QTD'), + ] + + nivel = 4 + +class RegistroK300(Registro): + """ + PRODUÇÃO CONJUNTA – INDUSTRIALIZAÇÃO EFETUADA POR + TERCEIROS + """ + campos = [ + CampoFixo(1, 'REG', 'K300'), + CampoData(2, 'DT_PROD'), + ] + + nivel = 3 + +class RegistroK301(Registro): + """ + PRODUÇÃO CONJUNTA – INDUSTRIALIZAÇÃO EFETUADA POR + TERCEIROS – ITENS PRODUZIDOS + """ + campos = [ + CampoFixo(1, 'REG', 'K301'), + Campo(2, 'COD_ITEM'), + CampoNumerico(3, 'QTD'), + ] + + nivel = 4 + +class RegistroK302(Registro): + """ + PRODUÇÃO CONJUNTA – INDUSTRIALIZAÇÃO EFETUADA POR + TERCEIROS – INSUMOS CONSUMIDOS + """ + campos = [ + CampoFixo(1, 'REG', 'K302'), + Campo(2, 'COD_ITEM'), + CampoNumerico(3, 'QTD'), + ] + + nivel = 4 class RegistroK990(Registro): """ @@ -2682,6 +3426,7 @@ class RegistroK990(Registro): CampoNumerico(2, 'QTD_LIN_K'), ] + nivel = 1 class Registro1001(Registro): """ @@ -2692,6 +3437,7 @@ class Registro1001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class Registro1010(Registro): """ @@ -2713,6 +3459,7 @@ class Registro1010(Registro): Campo(13, 'IND_GIAF4'), ] + nivel = 2 class Registro1100(Registro): """ @@ -2722,17 +3469,18 @@ class Registro1100(Registro): CampoFixo(1, 'REG', '1100'), Campo(2, 'IND_DOC'), Campo(3, 'NRO_DE'), - Campo(4, 'DT_DE'), + CampoData(4, 'DT_DE'), Campo(5, 'NAT_EXP'), Campo(6, 'NRO_RE'), - Campo(7, 'DT_RE'), + CampoData(7, 'DT_RE'), Campo(8, 'CHC_EMB'), - Campo(9, 'DT_CHC'), - Campo(10, 'DT_AVB'), + CampoData(9, 'DT_CHC'), + CampoData(10, 'DT_AVB'), Campo(11, 'TP_CHC'), Campo(12, 'PAIS'), ] + nivel = 2 class Registro1105(Registro): """ @@ -2742,12 +3490,13 @@ class Registro1105(Registro): CampoFixo(1, 'REG', '1105'), Campo(2, 'COD_MOD'), Campo(3, 'SERIE'), - Campo(4, 'NUM_DOC'), - Campo(5, 'CHV_NFE'), - Campo(6, 'DT_DOC'), + CampoNumerico(4, 'NUM_DOC'), + CampoChaveEletronica(5, 'CHV_NFE'), + CampoData(6, 'DT_DOC'), Campo(7, 'COD_ITEM'), ] + nivel = 3 class Registro1110(Registro): """ @@ -2758,14 +3507,15 @@ class Registro1110(Registro): Campo(2, 'COD_PART'), Campo(3, 'COD_MOD'), Campo(4, 'SER'), - Campo(5, 'NUM_DOC'), - Campo(6, 'DT_DOC'), - Campo(7, 'CHV_NFE'), + CampoNumerico(5, 'NUM_DOC'), + CampoData(6, 'DT_DOC'), + CampoChaveEletronica(7, 'CHV_NFE'), Campo(8, 'NR_ MEMO'), - Campo(9, 'QTD'), + CampoNumerico(9, 'QTD'), Campo(10, 'UNID'), ] + nivel = 4 class Registro1200(Registro): """ @@ -2781,6 +3531,7 @@ class Registro1200(Registro): Campo(7, 'SLD_CRED_FIM'), ] + nivel = 2 class Registro1210(Registro): """ @@ -2792,6 +3543,7 @@ class Registro1210(Registro): Campo(3, 'NR_DOC'), ] + nivel = 3 class Registro1300(Registro): """ @@ -2800,7 +3552,7 @@ class Registro1300(Registro): campos = [ CampoFixo(1, 'REG', '1300'), Campo(2, 'COD_ITEM'), - Campo(3, 'DT_FECH'), + CampoData(3, 'DT_FECH'), Campo(4, 'ESTQ_ABERT'), Campo(5, 'VOL_ENTR'), Campo(6, 'VOL_DISP'), @@ -2811,6 +3563,7 @@ class Registro1300(Registro): Campo(11, 'FECH_FISICO'), ] + nivel = 2 class Registro1310(Registro): """ @@ -2829,6 +3582,7 @@ class Registro1310(Registro): Campo(10, 'FECH_FISICO'), ] + nivel = 3 class Registro1320(Registro): """ @@ -2840,7 +3594,7 @@ class Registro1320(Registro): Campo(3, 'NR_INTERV'), Campo(4, 'MOT_INTERV'), Campo(5, 'NOM_INTERV'), - Campo(6, 'CNPJ_INTERV'), + CampoCNPJ(6, 'CNPJ_INTERV'), Campo(7, 'CPF_INTERV'), Campo(8, 'VAL_FECHA'), Campo(9, 'VAL_ABERT'), @@ -2848,6 +3602,7 @@ class Registro1320(Registro): Campo(11, 'VOL_VENDAS'), ] + nivel = 4 class Registro1350(Registro): """ @@ -2861,6 +3616,7 @@ class Registro1350(Registro): Campo(5, 'TIPO_MEDICAO'), ] + nivel = 2 class Registro1360(Registro): """ @@ -2869,9 +3625,10 @@ class Registro1360(Registro): campos = [ CampoFixo(1, 'REG', '1360'), Campo(2, 'NUM_LACRE'), - Campo(3, 'DT_APLICACAO'), + CampoData(3, 'DT_APLICACAO'), ] + nivel = 3 class Registro1370(Registro): """ @@ -2884,6 +3641,7 @@ class Registro1370(Registro): Campo(4, 'NUM_TANQUE'), ] + nivel = 3 class Registro1390(Registro): """ @@ -2894,6 +3652,7 @@ class Registro1390(Registro): Campo(2, 'COD_PROD'), ] + nivel = 2 class Registro1391(Registro): """ @@ -2901,10 +3660,10 @@ class Registro1391(Registro): """ campos = [ CampoFixo(1, 'REG', '1391'), - Campo(2, 'DT_REGISTRO'), - Campo(3, 'QTD_MOID'), + CampoData(2, 'DT_REGISTRO'), + CampoNumerico(3, 'QTD_MOID'), Campo(4, 'ESTQ_INI'), - Campo(5, 'QTD_PRODUZ'), + CampoNumerico(5, 'QTD_PRODUZ'), Campo(6, 'ENT_ANID_HID'), Campo(7, 'OUTR_ENTR'), Campo(8, 'PERDA'), @@ -2919,6 +3678,7 @@ class Registro1391(Registro): Campo(17, 'OBS'), ] + nivel = 3 class Registro1400(Registro): """ @@ -2931,6 +3691,7 @@ class Registro1400(Registro): Campo(4, 'VALOR'), ] + nivel = 2 class Registro1500(Registro): """ @@ -2942,30 +3703,31 @@ class Registro1500(Registro): Campo(3, 'IND_EMIT'), Campo(4, 'COD_PART'), Campo(5, 'COD_MOD'), - Campo(6, 'COD_SIT'), + CampoNumerico(6, 'COD_SIT'), Campo(7, 'SER'), - Campo(8, 'SUB'), + CampoNumerico(8, 'SUB'), Campo(9, 'COD_CONS'), - Campo(10, 'NUM_DOC'), - Campo(11, 'DT_DOC'), - Campo(12, 'DT_E_S'), - Campo(13, 'VL_DOC'), - Campo(14, 'VL_DESC'), - Campo(15, 'VL_FORN'), - Campo(16, 'VL_SERV_NT'), - Campo(17, 'VL_TERC'), - Campo(18, 'VL_DA'), - Campo(19, 'VL_BC_ICMS'), - Campo(20, 'VL_ICMS'), - Campo(21, 'VL_BC_ICMS_ST'), - Campo(22, 'VL_ICMS_ST'), + CampoNumerico(10, 'NUM_DOC'), + CampoData(11, 'DT_DOC'), + CampoData(12, 'DT_E_S'), + CampoNumerico(13, 'VL_DOC'), + CampoNumerico(14, 'VL_DESC'), + CampoNumerico(15, 'VL_FORN'), + CampoNumerico(16, 'VL_SERV_NT'), + CampoNumerico(17, 'VL_TERC'), + CampoNumerico(18, 'VL_DA'), + CampoNumerico(19, 'VL_BC_ICMS'), + CampoNumerico(20, 'VL_ICMS'), + CampoNumerico(21, 'VL_BC_ICMS_ST'), + CampoNumerico(22, 'VL_ICMS_ST'), Campo(23, 'COD_INF'), - Campo(24, 'VL_PIS'), - Campo(25, 'VL_COFINS'), + CampoNumerico(24, 'VL_PIS'), + CampoNumerico(25, 'VL_COFINS'), Campo(26, 'TP_LIGACAO'), Campo(27, 'COD_GRUPO_TENSAO'), ] + nivel = 2 class Registro1510(Registro): """ @@ -2976,25 +3738,26 @@ class Registro1510(Registro): Campo(2, 'NUM_ITEM'), Campo(3, 'COD_ITEM'), Campo(4, 'COD_CLASS'), - Campo(5, 'QTD'), + CampoNumerico(5, 'QTD'), Campo(6, 'UNID'), - Campo(7, 'VL_ITEM'), - Campo(8, 'VL_DESC'), - Campo(9, 'CST_ICMS'), - Campo(10, 'CFOP'), - Campo(11, 'VL_BC_ICMS'), - Campo(12, 'ALIQ_ICMS'), - Campo(13, 'VL_ICMS'), - Campo(14, 'VL_BC_ICMS_ST'), - Campo(15, 'ALIQ_ST'), - Campo(16, 'VL_ICMS_ST'), + CampoNumerico(7, 'VL_ITEM'), + CampoNumerico(8, 'VL_DESC'), + CampoNumerico(9, 'CST_ICMS'), + CampoNumerico(10, 'CFOP'), + CampoNumerico(11, 'VL_BC_ICMS'), + CampoNumerico(12, 'ALIQ_ICMS'), + CampoNumerico(13, 'VL_ICMS'), + CampoNumerico(14, 'VL_BC_ICMS_ST'), + CampoNumerico(15, 'ALIQ_ST'), + CampoNumerico(16, 'VL_ICMS_ST'), Campo(17, 'IND_REC'), Campo(18, 'COD_PART'), - Campo(19, 'VL_PIS'), - Campo(20, 'VL_COFINS'), + CampoNumerico(19, 'VL_PIS'), + CampoNumerico(20, 'VL_COFINS'), Campo(21, 'COD_CTA'), ] + nivel = 3 class Registro1600(Registro): """ @@ -3007,6 +3770,7 @@ class Registro1600(Registro): Campo(4, 'TOT_DEBITO'), ] + nivel = 2 class Registro1700(Registro): """ @@ -3017,12 +3781,13 @@ class Registro1700(Registro): Campo(2, 'COD_DISP'), Campo(3, 'COD_MOD'), Campo(4, 'SER'), - Campo(5, 'SUB'), - Campo(6, 'NUM_DOC_INI'), - Campo(7, 'NUM_DOC_FIN'), + CampoNumerico(5, 'SUB'), + CampoNumerico(6, 'NUM_DOC_INI'), + CampoNumerico(7, 'NUM_DOC_FIN'), Campo(8, 'NUM_AUT'), ] + nivel = 2 class Registro1710(Registro): """ @@ -3030,10 +3795,11 @@ class Registro1710(Registro): """ campos = [ CampoFixo(1, 'REG', '1710'), - Campo(2, 'NUM_DOC_INI'), - Campo(3, 'NUM_DOC_FIN'), + CampoNumerico(2, 'NUM_DOC_INI'), + CampoNumerico(3, 'NUM_DOC_FIN'), ] + nivel = 3 class Registro1800(Registro): """ @@ -3041,17 +3807,18 @@ class Registro1800(Registro): """ campos = [ CampoFixo(1, 'REG', '1800'), - Campo(2, 'VL_CARGA'), - Campo(3, 'VL_PASS'), - Campo(4, 'VL_FAT'), + CampoNumerico(2, 'VL_CARGA'), + CampoNumerico(3, 'VL_PASS'), + CampoNumerico(4, 'VL_FAT'), Campo(5, 'IND_RAT'), - Campo(6, 'VL_ICMS_ANT'), - Campo(7, 'VL_BC_ICMS'), - Campo(8, 'VL_ICMS_APUR'), - Campo(9, 'VL_BC_ICMS_APUR'), - Campo(10, 'VL_DIF'), + CampoNumerico(6, 'VL_ICMS_ANT'), + CampoNumerico(7, 'VL_BC_ICMS'), + CampoNumerico(8, 'VL_ICMS_APUR'), + CampoNumerico(9, 'VL_BC_ICMS_APUR'), + CampoNumerico(10, 'VL_DIF'), ] + nivel = 2 class Registro1900(Registro): """ @@ -3063,6 +3830,7 @@ class Registro1900(Registro): Campo(3, 'DESCR_COMPL_OUT_APUR'), ] + nivel = 2 class Registro1910(Registro): """ @@ -3074,6 +3842,7 @@ class Registro1910(Registro): CampoData(3, 'DT_FIN'), ] + nivel = 3 class Registro1920(Registro): """ @@ -3081,20 +3850,21 @@ class Registro1920(Registro): """ campos = [ CampoFixo(1, 'REG', '1920'), - Campo(2, 'VL_TOT_TRANSF_DEBITOS_OA'), - Campo(3, 'VL_TOT_AJ_DEBITOS_OA'), - Campo(4, 'VL_ESTORNOS_CRED_OA'), - Campo(5, 'VL_TOT_TRANSF_CREDITOS_OA'), - Campo(6, 'VL_TOT_AJ_CREDITOS_OA'), - Campo(7, 'VL_ESTORNOS_DEB_OA'), - Campo(8, 'VL_SLD_CREDOR_ANT_OA'), - Campo(9, 'VL_SLD_APURADO_OA'), - Campo(10, 'VL_TOT_DED'), - Campo(11, 'VL_ICMS_RECOLHER_OA'), - Campo(12, 'VL_SLD_CREDOR_TRANSP_OA'), + CampoNumerico(2, 'VL_TOT_TRANSF_DEBITOS_OA'), + CampoNumerico(3, 'VL_TOT_AJ_DEBITOS_OA'), + CampoNumerico(4, 'VL_ESTORNOS_CRED_OA'), + CampoNumerico(5, 'VL_TOT_TRANSF_CREDITOS_OA'), + CampoNumerico(6, 'VL_TOT_AJ_CREDITOS_OA'), + CampoNumerico(7, 'VL_ESTORNOS_DEB_OA'), + CampoNumerico(8, 'VL_SLD_CREDOR_ANT_OA'), + CampoNumerico(9, 'VL_SLD_APURADO_OA'), + CampoNumerico(10, 'VL_TOT_DED'), + CampoNumerico(11, 'VL_ICMS_RECOLHER_OA'), + CampoNumerico(12, 'VL_SLD_CREDOR_TRANSP_OA'), Campo(13, 'DEB_ESP_OA'), ] + nivel = 4 class Registro1921(Registro): """ @@ -3103,9 +3873,10 @@ class Registro1921(Registro): campos = [ CampoFixo(1, 'REG', '1921'), Campo(2, 'COD_AJ_APUR'), - Campo(3, 'VL_AJ_APUR'), + CampoNumerico(3, 'VL_AJ_APUR'), ] + nivel = 5 class Registro1922(Registro): """ @@ -3120,6 +3891,7 @@ class Registro1922(Registro): Campo(6, 'TXT_COMPL'), ] + nivel = 6 class Registro1923(Registro): """ @@ -3130,13 +3902,14 @@ class Registro1923(Registro): Campo(2, 'COD_PART'), Campo(3, 'COD_MOD'), Campo(4, 'SER'), - Campo(5, 'SUB'), - Campo(6, 'NUM_DOC'), - Campo(7, 'DT_DOC'), + CampoNumerico(5, 'SUB'), + CampoNumerico(6, 'NUM_DOC'), + CampoData(7, 'DT_DOC'), Campo(8, 'COD_ITEM'), - Campo(9, 'VL_AJ_ITEM'), + CampoNumerico(9, 'VL_AJ_ITEM'), ] + nivel = 6 class Registro1925(Registro): """ @@ -3145,10 +3918,11 @@ class Registro1925(Registro): campos = [ CampoFixo(1, 'REG', '1925'), Campo(2, 'COD_INF_ADIC'), - Campo(3, 'VL_INF_ADIC'), + CampoNumerico(3, 'VL_INF_ADIC'), Campo(4, 'DESCR_COMPL_AJ'), ] + nivel = 5 class Registro1926(Registro): """ @@ -3157,8 +3931,8 @@ class Registro1926(Registro): campos = [ CampoFixo(1, 'REG', '1926'), Campo(2, 'COD_OR'), - Campo(3, 'VL_OR'), - Campo(4, 'DT_VCTO'), + CampoNumerico(3, 'VL_OR'), + CampoData(4, 'DT_VCTO'), Campo(5, 'COD_REC'), Campo(6, 'NUM_PROC'), Campo(7, 'IND_PROC'), @@ -3167,6 +3941,93 @@ class Registro1926(Registro): Campo(10, 'MES_REF'), ] + nivel = 5 + +class Registro1960(Registro): + """ + GIAF 1 - GUIA DE INFORMAÇÃO E APURAÇÃO DE INCENTIVOS + FISCAIS E FINANCEIROS: INDÚSTRIA (CRÉDITO PRESUMIDO) + """ + campos = [ + CampoFixo(1, 'REG', '1960'), + Campo(2, 'IND_AP'), + CampoNumerico(3, 'G1_01'), + CampoNumerico(4, 'G1_02'), + CampoNumerico(5, 'G1_03'), + CampoNumerico(6, 'G1_04'), + CampoNumerico(7, 'G1_05'), + CampoNumerico(8, 'G1_06'), + CampoNumerico(9, 'G1_07'), + CampoNumerico(10, 'G1_08'), + CampoNumerico(11, 'G1_09'), + CampoNumerico(12, 'G1_10'), + CampoNumerico(13, 'G1_11'), + ] + + nivel = 2 + +class Registro1970(Registro): + """ + GIAF 3 - GUIA DE INFORMAÇÃO E APURAÇÃO DE INCENTIVOS + FISCAIS E FINANCEIROS: IMPORTAÇÃO (DIFERIMENTO NA ENTRADA E CRÉDITO + PRESUMIDO NA SAÍDA SUBSEQUENTE + """ + campos = [ + CampoFixo(1, 'REG', '1970'), + Campo(2, 'IND_AP'), + CampoNumerico(3, 'G3_01'), + CampoNumerico(4, 'G3_02'), + CampoNumerico(5, 'G3_03'), + CampoNumerico(6, 'G3_04'), + CampoNumerico(7, 'G3_05'), + CampoNumerico(8, 'G3_06'), + CampoNumerico(9, 'G3_07'), + CampoNumerico(10, 'G3_T'), + CampoNumerico(11, 'G3_08'), + CampoNumerico(12, 'G3_09'), + ] + + nivel = 2 + +class Registro1975(Registro): + """ + GIAF 3 - GUIA DE INFORMAÇÃO E APURAÇÃO DE INCENTIVOS + FISCAIS E FINANCEIROS: IMPORTAÇÃO (SAÍDAS INTERNAS POR FAIXA DE + ALÍQUOTA) + """ + campos = [ + CampoFixo(1, 'REG', '1975'), + CampoNumerico(2, 'ALIQ_IMP_BASE'), + CampoNumerico(3, 'G3_10'), + CampoNumerico(4, 'G3_11'), + CampoNumerico(5, 'G3_12'), + ] + + nivel = 3 + +class Registro1980(Registro): + """ + GIAF 4 GUIA DE INFORMAÇÃO E APURAÇÃO DE INCENTIVOS + FISCAIS E FINANCEIROS: CENTRAL DE DISTRIBUIÇÃO (ENTRADAS/SAÍDAS + """ + campos = [ + CampoFixo(1, 'REG', '1980'), + CampoNumerico(2, 'IND_AP'), + CampoNumerico(3, 'G4_01'), + CampoNumerico(4, 'G4_02'), + CampoNumerico(5, 'G4_03'), + CampoNumerico(6, 'G4_04'), + CampoNumerico(7, 'G4_05'), + CampoNumerico(8, 'G4_06'), + CampoNumerico(9, 'G4_07'), + CampoNumerico(10, 'G4_08'), + CampoNumerico(11, 'G4_09'), + CampoNumerico(12, 'G4_10'), + CampoNumerico(13, 'G4_11'), + CampoNumerico(14, 'G4_12'), + ] + + nivel = 2 class Registro1990(Registro): """ @@ -3177,6 +4038,7 @@ class Registro1990(Registro): CampoNumerico(2, 'QTD_LIN_1'), ] + nivel = 1 class Registro9001(Registro): """ @@ -3187,6 +4049,7 @@ class Registro9001(Registro): Campo(2, 'IND_MOV'), ] + nivel = 1 class Registro9900(Registro): """ @@ -3195,9 +4058,10 @@ class Registro9900(Registro): campos = [ CampoFixo(1, 'REG', '9900'), Campo(2, 'REG_BLC'), - Campo(3, 'QTD_REG_BLC'), + CampoNumerico(3, 'QTD_REG_BLC'), ] + nivel = 2 class Registro9990(Registro): """ @@ -3208,6 +4072,7 @@ class Registro9990(Registro): CampoNumerico(2, 'QTD_LIN_9'), ] + nivel = 1 class Registro9999(Registro): """ @@ -3217,3 +4082,5 @@ class Registro9999(Registro): CampoFixo(1, 'REG', '9999'), CampoNumerico(2, 'QTD_LIN'), ] + + nivel = 0 From 2692d23ff555758a7ab4ac58e630ca9b0e7e5347 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:01:19 -0300 Subject: [PATCH 10/52] [fix] registro de abertura e encerramento do Bloco 9 --- sped/efd/pis_cofins/blocos.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sped/efd/pis_cofins/blocos.py b/sped/efd/pis_cofins/blocos.py index 5246afa..5be42b7 100644 --- a/sped/efd/pis_cofins/blocos.py +++ b/sped/efd/pis_cofins/blocos.py @@ -30,7 +30,6 @@ class Bloco0(Bloco): registro_abertura = Registro0001() registro_encerramento = Registro0990() - class BlocoA(Bloco): """ Documentos Fiscais - Serviços (ISS) @@ -38,7 +37,6 @@ class BlocoA(Bloco): registro_abertura = RegistroA001() registro_encerramento = RegistroA990() - class BlocoC(Bloco): """ Documentos Fiscais I – Mercadorias (ICMS/IPI) @@ -99,5 +97,5 @@ class Bloco9(Bloco): """ Controle e Encerramento do Arquivo Digital """ - registro_abertura = Registro0001() - registro_encerramento = Registro0990() + registro_abertura = Registro9001() + registro_encerramento = Registro9990() From 3db188c9de03976f0e9e5aa12b9476f934f18ff8 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:02:15 -0300 Subject: [PATCH 11/52] =?UTF-8?q?[new]=20nivel=20e=20atualiza=C3=A7=C3=A3o?= =?UTF-8?q?=20dos=20registros?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/efd/pis_cofins/registros.py | 1031 +++++++++++++++++++----------- 1 file changed, 659 insertions(+), 372 deletions(-) diff --git a/sped/efd/pis_cofins/registros.py b/sped/efd/pis_cofins/registros.py index fc1762b..49d4119 100644 --- a/sped/efd/pis_cofins/registros.py +++ b/sped/efd/pis_cofins/registros.py @@ -1,13 +1,16 @@ # -*- coding: utf-8 -*- +from ...registros import Registro from ...campos import Campo -from ...campos import CampoAlfanumerico -from ...campos import CampoCNPJ from ...campos import CampoData from ...campos import CampoFixo from ...campos import CampoNumerico +from ...campos import CampoAlfanumerico from ...campos import CampoRegex -from ...registros import Registro +from ...campos import CampoCNPJ +from ...campos import CampoCPF +from ...campos import CampoCPFouCNPJ +from ...campos import CampoChaveEletronica class Registro0000(Registro): @@ -34,12 +37,13 @@ class Registro0000(Registro): Campo(8, 'NOME', obrigatorio=True), CampoCNPJ(9, 'CNPJ', obrigatorio=True), Campo(10, 'UF', obrigatorio=True), - Campo(11, 'COD_MUN', obrigatorio=True), + CampoNumerico(11, 'COD_MUN', obrigatorio=True), Campo(12, 'SUFRAMA'), Campo(13, 'IND_NAT_PJ'), Campo(14, 'IND_ATIV', obrigatorio=True), ] - + + nivel = 0 class Registro0001(Registro): """ @@ -49,7 +53,8 @@ class Registro0001(Registro): CampoFixo(1, 'REG', '0001'), Campo(2, 'IND_MOV', obrigatorio=True) ] - + + nivel = 1 class Registro0035(Registro): """ @@ -61,7 +66,8 @@ class Registro0035(Registro): Campo(3, 'DESC_SCP', obrigatorio=True), Campo(4, 'INF_COMP', obrigatorio=True), ] - + + nivel = 2 class Registro0100(Registro): """ @@ -70,7 +76,7 @@ class Registro0100(Registro): campos = [ CampoFixo(1, 'REG', '0100'), Campo(2, 'NOME', obrigatorio=True), - Campo(3, 'CPF', obrigatorio=True), + CampoCPF(3, 'CPF', obrigatorio=True), Campo(4, 'CRC', obrigatorio=True), CampoCNPJ(5, 'CNPJ'), Campo(6, 'CEP'), @@ -81,9 +87,10 @@ class Registro0100(Registro): Campo(11, 'FONE'), Campo(12, 'FAX'), Campo(13, 'EMAIL'), - Campo(14, 'COD_MUN'), + CampoNumerico(14, 'COD_MUN'), ] - + + nivel = 2 class Registro0110(Registro): """ @@ -96,7 +103,8 @@ class Registro0110(Registro): Campo(4, 'COD_TIPO_CONT'), Campo(5, 'IND_REG_CUM'), ] - + + nivel = 2 class Registro0111(Registro): """ @@ -110,7 +118,8 @@ class Registro0111(Registro): CampoNumerico(5, 'REC_BRU_CUM', obrigatorio=True), CampoNumerico(6, 'REC_BRU_TOTAL', obrigatorio=True), ] - + + nivel = 3 class Registro0120(Registro): """ @@ -121,7 +130,8 @@ class Registro0120(Registro): Campo(2, 'MES_DISPENSA', obrigatorio=True), Campo(3, 'INF_COMP'), ] - + + nivel = 2 class Registro0140(Registro): """ @@ -134,11 +144,12 @@ class Registro0140(Registro): CampoCNPJ(4, 'CNPJ', obrigatorio=True), Campo(5, 'UF', obrigatorio=True), Campo(6, 'IE'), - Campo(7, 'COD_MUN', obrigatorio=True), + CampoNumerico(7, 'COD_MUN', obrigatorio=True), Campo(8, 'IM'), Campo(9, 'SUFRAMA'), ] - + + nivel = 2 class Registro0145(Registro): """ @@ -152,7 +163,8 @@ class Registro0145(Registro): CampoNumerico(5, 'VL_REC_DEMAIS_ATIV'), Campo(6, 'INFO_COMPL'), ] - + + nivel = 3 class Registro0150(Registro): """ @@ -164,16 +176,17 @@ class Registro0150(Registro): Campo(3, 'NOME', obrigatorio=True), Campo(4, 'COD_PAIS', obrigatorio=True), CampoCNPJ(5, 'CNPJ'), - Campo(6, 'CPF'), + CampoCPF(6, 'CPF'), Campo(7, 'IE'), - Campo(8, 'COD_MUN'), + CampoNumerico(8, 'COD_MUN'), Campo(9, 'SUFRAMA'), Campo(10, 'END'), Campo(11, 'NUM'), Campo(12, 'COMPL'), Campo(13, 'BAIRRO'), ] - + + nivel = 3 class Registro0190(Registro): """ @@ -184,7 +197,8 @@ class Registro0190(Registro): Campo(2, 'UNID', obrigatorio=True), Campo(3, 'DESCR', obrigatorio=True), ] - + + nivel = 3 class Registro0200(Registro): """ @@ -204,7 +218,8 @@ class Registro0200(Registro): Campo(11, 'COD_LST'), CampoNumerico(12, 'ALIQ_ICMS'), ] - + + nivel = 3 class Registro0205(Registro): """ @@ -217,7 +232,8 @@ class Registro0205(Registro): CampoData(4, 'DT_FIM', obrigatorio=True), Campo(5, 'COD_ANT_ITEM'), ] - + + nivel = 4 class Registro0206(Registro): """ @@ -227,7 +243,8 @@ class Registro0206(Registro): CampoFixo(1, 'REG', '0206'), Campo(2, 'COD_COMB', obrigatorio=True), ] - + + nivel = 4 class Registro0208(Registro): """ @@ -239,7 +256,8 @@ class Registro0208(Registro): Campo(3, 'COD_GRU', obrigatorio=True), Campo(4, 'MARCA_COM', obrigatorio=True), ] - + + nivel = 4 class Registro0400(Registro): """ @@ -250,7 +268,8 @@ class Registro0400(Registro): Campo(2, 'COD_NAT', obrigatorio=True), Campo(3, 'DESCR_NAT', obrigatorio=True), ] - + + nivel = 3 class Registro0450(Registro): """ @@ -261,7 +280,8 @@ class Registro0450(Registro): Campo(2, 'COD_INF', obrigatorio=True), Campo(3, 'TXT', obrigatorio=True), ] - + + nivel = 3 class Registro0500(Registro): """ @@ -278,7 +298,8 @@ class Registro0500(Registro): Campo(8, 'COD_CTA_REF'), CampoCNPJ(9, 'CNPJ_EST'), ] - + + nivel = 2 class Registro0600(Registro): """ @@ -290,7 +311,32 @@ class Registro0600(Registro): Campo(3, 'COD_CCUS', obrigatorio=True), Campo(4, 'CCUS', obrigatorio=True), ] + + nivel = 2 +class Registro0900(Registro): + """ + Composição das Receitas do Período - Receita Bruta e Demais Receitas + """ + campos = [ + CampoFixo(1, 'REG', '0900'), + CampoNumerico(2, 'REC_TOTAL_BLOCO_A', obrigatorio=True), + CampoNumerico(3, 'REC_NRB_BLOCO_A'), + CampoNumerico(4, 'REC_TOTAL_BLOCO_C', obrigatorio=True), + CampoNumerico(5, 'REC_NRB_BLOCO_C'), + CampoNumerico(6, 'REC_TOTAL_BLOCO_D', obrigatorio=True), + CampoNumerico(7, 'REC_NRB_BLOCO_D'), + CampoNumerico(8, 'REC_TOTAL_BLOCO_F', obrigatorio=True), + CampoNumerico(9, 'REC_NRB_BLOCO_F'), + CampoNumerico(10, 'REC_TOTAL_BLOCO_I', obrigatorio=True), + CampoNumerico(11, 'REC_NRB_BLOCO_I'), + CampoNumerico(12, 'REC_TOTAL_BLOCO_1', obrigatorio=True), + CampoNumerico(13, 'REC_NRB_BLOCO_1'), + CampoNumerico(14, 'REC_TOTAL_PERIODO', obrigatorio=True), + CampoNumerico(15, 'REC_TOTAL_NRB_PERÍODO'), + ] + + nivel = 2 class Registro0990(Registro): """ @@ -300,7 +346,9 @@ class Registro0990(Registro): CampoFixo(1, 'REG', '0990'), CampoNumerico(2, 'QTD_LIN_0', obrigatorio=True), ] - + + nivel = 1 + class RegistroA001(Registro): """ @@ -310,7 +358,8 @@ class RegistroA001(Registro): CampoFixo(1, 'REG', 'A001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + + nivel = 1 class RegistroA010(Registro): """ @@ -320,7 +369,7 @@ class RegistroA010(Registro): CampoFixo(1, 'REG', 'A010'), CampoCNPJ(2, 'CNPJ', obrigatorio=True), ] - + nivel = 2 class RegistroA100(Registro): """ @@ -331,11 +380,11 @@ class RegistroA100(Registro): Campo(2, 'IND_OPER', obrigatorio=True), Campo(3, 'IND_EMIT', obrigatorio=True), Campo(4, 'COD_PART'), - Campo(5, 'COD_SIT', obrigatorio=True), + CampoNumerico(5, 'COD_SIT', obrigatorio=True), Campo(6, 'SER'), - Campo(7, 'SUB'), - Campo(8, 'NUM_DOC', obrigatorio=True), - Campo(9, 'CHV_NFSE'), + CampoNumerico(7, 'SUB'), + CampoNumerico(8, 'NUM_DOC', obrigatorio=True), + CampoChaveEletronica(9, 'CHV_NFSE'), CampoData(10, 'DT_DOC', obrigatorio=True), CampoData(11, 'DT_EXE_SERV', obrigatorio=True), CampoNumerico(12, 'VL_DOC'), @@ -349,7 +398,7 @@ class RegistroA100(Registro): CampoNumerico(20, 'VL_COFINS_RET'), CampoNumerico(21, 'VL_ISS'), ] - + nivel = 3 class RegistroA110(Registro): """ @@ -360,7 +409,8 @@ class RegistroA110(Registro): Campo(2, 'COD_INF', obrigatorio=True), Campo(3, 'TXT_COMPL'), ] - + + nivel = 4 class RegistroA111(Registro): """ @@ -371,7 +421,8 @@ class RegistroA111(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroA120(Registro): """ @@ -388,7 +439,8 @@ class RegistroA120(Registro): CampoData(8, 'DT_PAG_COFINS'), Campo(9, 'LOC_EXE_SERV', obrigatorio=True), ] - + + nivel = 4 class RegistroA170(Registro): """ @@ -403,18 +455,19 @@ class RegistroA170(Registro): CampoNumerico(6, 'VL_DESC'), Campo(7, 'NAT_BC_CRED'), Campo(8, 'IND_ORIG_CRED'), - Campo(9, 'CST_PIS', obrigatorio=True), + CampoNumerico(9, 'CST_PIS', obrigatorio=True), CampoNumerico(10, 'VL_BC_PIS'), CampoNumerico(11, 'ALIQ_PIS'), CampoNumerico(12, 'VL_PIS'), - Campo(13, 'CST_COFINS', obrigatorio=True), + CampoNumerico(13, 'CST_COFINS', obrigatorio=True), CampoNumerico(14, 'VL_BC_COFINS'), CampoNumerico(15, 'ALIQ_COFINS'), CampoNumerico(16, 'VL_COFINS'), Campo(17, 'COD_CTA'), Campo(18, 'COD_CCUS'), ] - + + nivel = 4 class RegistroA990(Registro): """ @@ -424,7 +477,8 @@ class RegistroA990(Registro): CampoFixo(1, 'REG', 'A990'), CampoNumerico(2, 'QTD_LIN_A', obrigatorio=True), ] - + + nivel = 1 class RegistroC001(Registro): """ @@ -434,7 +488,8 @@ class RegistroC001(Registro): CampoFixo(1, 'REG', 'C001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + + nivel = 1 class RegistroC010(Registro): """ @@ -445,27 +500,28 @@ class RegistroC010(Registro): CampoCNPJ(2, 'CNPJ', obrigatorio=True), Campo(3, 'IND_ESCRI'), ] - + + nivel = 2 class RegistroC100(Registro): """ - Documento - Nota Fiscal (código 01), Nota Fiscal Avulsa (código 1B), Nota Fiscal de Produtor (código 04) e - NF-e (código 55) + Documento - Nota Fiscal (Código 01), Nota Fiscal Avulsa (Código 1B), Nota Fiscal de + Produtor (Código 04), NF-e (Código 55) e NFC-e (Código 65). """ campos = [ CampoFixo(1, 'REG', 'C100'), Campo(2, 'IND_OPER', obrigatorio=True), Campo(3, 'IND_EMIT', obrigatorio=True), Campo(4, 'COD_PART', obrigatorio=True), - Campo(5, 'COD_MOD', obrigatorio=True), - Campo(6, 'COD_SIT;', obrigatorio=True), + Campo(5, 'COD_MOD', obrigatorio=True), + CampoNumerico(6, 'COD_SIT', obrigatorio=True), Campo(7, 'SER'), - Campo(8, 'NUM_DOC', obrigatorio=True), - Campo(9, 'CHV_NFE'), - Campo(10, 'CHV_NFE', obrigatorio=True), - CampoData(11, 'DT_DOC'), - CampoData(12, 'DT_E_S', obrigatorio=True), - CampoNumerico(13, 'VL_DOC', obrigatorio=True), + CampoNumerico(8, 'NUM_DOC', obrigatorio=True), + CampoChaveEletronica(9, 'CHV_NFE'), + CampoData(10, 'DT_DOC', obrigatorio=True), + CampoData(11, 'DT_E_S'), + CampoNumerico(12, 'VL_DOC', obrigatorio=True), + Campo(13, 'IND_PGTO', obrigatorio=True), CampoNumerico(14, 'VL_DESC'), CampoNumerico(15, 'VL_ABAT_NT'), CampoNumerico(16, 'VL_MERC'), @@ -483,7 +539,8 @@ class RegistroC100(Registro): CampoNumerico(28, 'VL_PIS_ST'), CampoNumerico(29, 'VL_COFINS_ST'), ] - + + nivel = 3 class RegistroC110(Registro): """ @@ -494,7 +551,8 @@ class RegistroC110(Registro): Campo(2, 'COD_INF', obrigatorio=True), Campo(3, 'TXT_COMPL'), ] - + + nivel = 4 class RegistroC111(Registro): """ @@ -505,7 +563,8 @@ class RegistroC111(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC120(Registro): """ @@ -514,12 +573,13 @@ class RegistroC120(Registro): campos = [ CampoFixo(1, 'REG', 'C120'), Campo(2, 'COD_DOC_IMP', obrigatorio=True), - Campo(3, 'NUM_DOC_IMP', obrigatorio=True), + CampoNumerico(3, 'NUM_DOC_IMP', obrigatorio=True), CampoNumerico(4, 'VL_PIS_IMP'), CampoNumerico(5, 'VL_COFINS_IMP'), Campo(6, 'NUM_ACDRAW'), ] - + + nivel = 4 class RegistroC170(Registro): """ @@ -527,16 +587,16 @@ class RegistroC170(Registro): """ campos = [ CampoFixo(1, 'REG', 'C170'), - Campo(2, 'NUM_ITEM', obrigatorio=True), + CampoNumerico(2, 'NUM_ITEM', obrigatorio=True), Campo(3, 'COD_ITEM', obrigatorio=True), Campo(4, 'DESCR_COMPL'), - Campo(5, 'QTD'), + CampoNumerico(5, 'QTD'), Campo(6, 'UNID'), CampoNumerico(7, 'VL_ITEM', obrigatorio=True), CampoNumerico(8, 'VL_DESC'), Campo(9, 'IND_MOV'), - Campo(10, 'CST_ICMS'), - Campo(11, 'CFOP', obrigatorio=True), + CampoNumerico(10, 'CST_ICMS'), + CampoNumerico(11, 'CFOP', obrigatorio=True), Campo(12, 'COD_NAT'), CampoNumerico(13, 'VL_BC_ICMS'), CampoNumerico(14, 'ALIQ_ICMS'), @@ -550,21 +610,22 @@ class RegistroC170(Registro): CampoNumerico(22, 'VL_BC_IPI'), CampoNumerico(23, 'ALIQ_IPI'), CampoNumerico(24, 'VL_IPI'), - Campo(25, 'CST_PIS', obrigatorio=True), + CampoNumerico(25, 'CST_PIS', obrigatorio=True), CampoNumerico(26, 'VL_BC_PIS'), CampoNumerico(27, 'ALIQ_PIS'), - Campo(28, 'QUANT_BC_PIS'), + CampoNumerico(28, 'QUANT_BC_PIS'), CampoNumerico(29, 'ALIQ_PIS_QUANT'), CampoNumerico(30, 'VL_PIS'), - Campo(31, 'CST_COFINS', obrigatorio=True), + CampoNumerico(31, 'CST_COFINS', obrigatorio=True), CampoNumerico(32, 'VL_BC_COFINS'), CampoNumerico(33, 'ALIQ_COFINS'), - Campo(34, 'QUANT_BC_COFINS'), + CampoNumerico(34, 'QUANT_BC_COFINS'), CampoNumerico(35, 'ALIQ_COFINS_QUANT'), CampoNumerico(36, 'VL_COFINS'), Campo(37, 'COD_CTA'), ] - + + nivel = 4 class RegistroC175(Registro): """ @@ -572,16 +633,16 @@ class RegistroC175(Registro): """ campos = [ CampoFixo(1, 'REG', 'C175'), - Campo(2, 'CFOP', obrigatorio=True), + CampoNumerico(2, 'CFOP', obrigatorio=True), CampoNumerico(3, 'VL_OPR', obrigatorio=True), CampoNumerico(4, 'VL_DESC'), - Campo(5, 'CST_PIS'), + CampoNumerico(5, 'CST_PIS'), CampoNumerico(6, 'VL_BC_PIS'), CampoNumerico(7, 'ALIQ_PIS'), Campo(8, 'QUANT_BC_PIS'), CampoNumerico(9, 'ALIQ_PIS_QUANT'), CampoNumerico(10, 'VL_PIS'), - Campo(11, 'CST_COFINS', obrigatorio=True), + CampoNumerico(11, 'CST_COFINS', obrigatorio=True), CampoNumerico(12, 'VL_BC_COFINS'), CampoNumerico(13, 'ALIQ_COFINS'), Campo(14, 'QUANT_BC_COFINS'), @@ -590,7 +651,8 @@ class RegistroC175(Registro): Campo(17, 'COD_CTA'), Campo(18, 'INFO_COMPL'), ] - + + nivel = 4 class RegistroC180(Registro): """ @@ -606,7 +668,8 @@ class RegistroC180(Registro): Campo(7, 'EX_IPI'), CampoNumerico(8, 'VL_TOT_ITEM', obrigatorio=True), ] - + + nivel = 3 class RegistroC181(Registro): """ @@ -614,8 +677,8 @@ class RegistroC181(Registro): """ campos = [ CampoFixo(1, 'REG', 'C181'), - Campo(2, 'CST_PIS', obrigatorio=True), - Campo(3, 'CFOP', obrigatorio=True), + CampoNumerico(2, 'CST_PIS', obrigatorio=True), + CampoNumerico(3, 'CFOP', obrigatorio=True), CampoNumerico(4, 'VL_ITEM', obrigatorio=True), CampoNumerico(5, 'VL_DESC'), CampoNumerico(6, 'VL_BC_PIS'), @@ -625,7 +688,8 @@ class RegistroC181(Registro): CampoNumerico(10, 'VL_PIS'), Campo(11, 'COD_CTA'), ] - + + nivel = 4 class RegistroC185(Registro): """ @@ -633,8 +697,8 @@ class RegistroC185(Registro): """ campos = [ CampoFixo(1, 'REG', 'C185'), - Campo(2, 'CST_COFINS', obrigatorio=True), - Campo(3, 'CFOP', obrigatorio=True), + CampoNumerico(2, 'CST_COFINS', obrigatorio=True), + CampoNumerico(3, 'CFOP', obrigatorio=True), CampoNumerico(4, 'VL_ITEM', obrigatorio=True), CampoNumerico(5, 'VL_DESC'), CampoNumerico(6, 'VL_BC_COFINS'), @@ -644,7 +708,8 @@ class RegistroC185(Registro): CampoNumerico(10, 'VL_COFINS'), Campo(11, 'COD_CTA'), ] - + + nivel = 4 class RegistroC188(Registro): """ @@ -655,7 +720,8 @@ class RegistroC188(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC190(Registro): """ @@ -672,7 +738,8 @@ class RegistroC190(Registro): Campo(7, 'EX_IPI'), CampoNumerico(8, 'VL_TOT_ITEM', obrigatorio=True), ] - + + nivel = 3 class RegistroC191(Registro): """ @@ -681,9 +748,9 @@ class RegistroC191(Registro): """ campos = [ CampoFixo(1, 'REG', 'C191'), - Campo(2, 'CNPJ_CPF_PART', obrigatorio=True), - Campo(3, 'CST_PIS', obrigatorio=True), - Campo(4, 'CFOP', obrigatorio=True), + CampoCPFouCNPJ(2, 'CNPJ_CPF_PART', obrigatorio=True), + CampoNumerico(3, 'CST_PIS', obrigatorio=True), + CampoNumerico(4, 'CFOP', obrigatorio=True), CampoNumerico(5, 'VL_ITEM', obrigatorio=True), CampoNumerico(6, 'VL_DESC'), CampoNumerico(7, 'VL_BC_PIS'), @@ -693,7 +760,8 @@ class RegistroC191(Registro): CampoNumerico(11, 'VL_PIS'), Campo(12, 'COD_CTA'), ] - + + nivel = 4 class RegistroC195(Registro): """ @@ -702,9 +770,9 @@ class RegistroC195(Registro): """ campos = [ CampoFixo(1, 'REG', 'C195'), - Campo(2, 'CNPJ_CPF_PART', obrigatorio=True), - Campo(3, 'CST_COFINS', obrigatorio=True), - Campo(4, 'CFOP', obrigatorio=True), + CampoCPFouCNPJ(2, 'CNPJ_CPF_PART', obrigatorio=True), + CampoNumerico(3, 'CST_COFINS', obrigatorio=True), + CampoNumerico(4, 'CFOP', obrigatorio=True), CampoNumerico(5, 'VL_ITEM', obrigatorio=True), CampoNumerico(6, 'VL_DESC'), CampoNumerico(7, 'VL_BC_COFINS'), @@ -714,7 +782,8 @@ class RegistroC195(Registro): CampoNumerico(11, 'VL_COFINS'), Campo(12, 'COD_CTA'), ] - + + nivel = 4 class RegistroC198(Registro): """ @@ -725,7 +794,8 @@ class RegistroC198(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC199(Registro): """ @@ -734,12 +804,13 @@ class RegistroC199(Registro): campos = [ CampoFixo(1, 'REG', 'C199'), Campo(2, 'COD_DOC_IMP', obrigatorio=True), - Campo(3, 'NUM_DOC__IMP', obrigatorio=True), + CampoNumerico(3, 'NUM_DOC__IMP', obrigatorio=True), CampoNumerico(4, 'VL_PIS_IMP'), CampoNumerico(5, 'VL_COFINS_IMP'), Campo(6, 'NUM_ACDRAW'), ] - + + nivel = 4 class RegistroC380(Registro): """ @@ -750,12 +821,13 @@ class RegistroC380(Registro): Campo(2, 'COD_MOD', obrigatorio=True), CampoData(3, 'DT_DOC_INI', obrigatorio=True), CampoData(4, 'DT_DOC_FIN', obrigatorio=True), - Campo(5, 'NUM_DOC_INI'), - Campo(6, 'NUM_DOC_FIN'), + CampoNumerico(5, 'NUM_DOC_INI'), + CampoNumerico(6, 'NUM_DOC_FIN'), CampoNumerico(7, 'VL_DOC', obrigatorio=True), CampoNumerico(8, 'VL_DOC_CANC', obrigatorio=True), ] - + + nivel = 3 class RegistroC381(Registro): """ @@ -763,7 +835,7 @@ class RegistroC381(Registro): """ campos = [ CampoFixo(1, 'REG', 'C381'), - Campo(2, 'CST_PIS', obrigatorio=True), + CampoNumerico(2, 'CST_PIS', obrigatorio=True), Campo(3, 'COD_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_ITEM', obrigatorio=True), CampoNumerico(5, 'VL_BC_PIS'), @@ -773,7 +845,8 @@ class RegistroC381(Registro): CampoNumerico(9, 'VL_PIS', obrigatorio=True), Campo(10, 'COD_CTA'), ] - + + nivel = 4 class RegistroC385(Registro): """ @@ -781,7 +854,7 @@ class RegistroC385(Registro): """ campos = [ CampoFixo(1, 'REG', 'C385'), - Campo(2, 'CST_COFINS', obrigatorio=True), + CampoNumerico(2, 'CST_COFINS', obrigatorio=True), Campo(3, 'COD_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_ITEM', obrigatorio=True), CampoNumerico(5, 'VL_BC_COFINS'), @@ -791,7 +864,8 @@ class RegistroC385(Registro): CampoNumerico(9, 'VL_COFINS', obrigatorio=True), Campo(10, 'COD_CTA'), ] - + + nivel = 4 class RegistroC395(Registro): """ @@ -803,11 +877,12 @@ class RegistroC395(Registro): Campo(3, 'COD_PART'), Campo(4, 'SER', obrigatorio=True), Campo(5, 'SUB_SER'), - Campo(6, 'NUM_DOC', obrigatorio=True), + CampoNumerico(6, 'NUM_DOC', obrigatorio=True), CampoData(7, 'DT_DOC', obrigatorio=True), CampoNumerico(8, 'VL_DOC', obrigatorio=True), ] - + + nivel = 3 class RegistroC396(Registro): """ @@ -819,17 +894,18 @@ class RegistroC396(Registro): CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_DESC'), Campo(5, 'NAT_BC_CRED', obrigatorio=True), - Campo(6, 'CST_PIS', obrigatorio=True), + CampoNumerico(6, 'CST_PIS', obrigatorio=True), CampoNumerico(7, 'VL_BC_PIS'), CampoNumerico(8, 'ALIQ_PIS'), CampoNumerico(9, 'VL_PIS'), - Campo(10, 'CST_COFINS', obrigatorio=True), + CampoNumerico(10, 'CST_COFINS', obrigatorio=True), CampoNumerico(11, 'VL_BC_COFINS'), CampoNumerico(12, 'ALIQ_COFINS'), CampoNumerico(13, 'VL_COFINS'), Campo(14, 'COD_CTA'), ] - + + nivel = 4 class RegistroC400(Registro): """ @@ -842,7 +918,8 @@ class RegistroC400(Registro): Campo(4, 'ECF_FAB', obrigatorio=True), Campo(5, 'ECF_CX', obrigatorio=True), ] - + + nivel = 3 class RegistroC405(Registro): """ @@ -857,7 +934,8 @@ class RegistroC405(Registro): Campo(6, 'GT_FIN', obrigatorio=True), CampoNumerico(7, 'VL_BRT', obrigatorio=True), ] - + + nivel = 4 class RegistroC481(Registro): """ @@ -865,7 +943,7 @@ class RegistroC481(Registro): """ campos = [ CampoFixo(1, 'REG', 'C481'), - Campo(2, 'CST_PIS', obrigatorio=True), + CampoNumerico(2, 'CST_PIS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_BC_PIS'), CampoNumerico(5, 'ALIQ_PIS'), @@ -875,7 +953,8 @@ class RegistroC481(Registro): Campo(9, 'COD_ITEM'), Campo(10, 'COD_CTA'), ] - + + nivel = 5 class RegistroC485(Registro): """ @@ -883,7 +962,7 @@ class RegistroC485(Registro): """ campos = [ CampoFixo(1, 'REG', 'C485'), - Campo(2, 'CST_COFINS', obrigatorio=True), + CampoNumerico(2, 'CST_COFINS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_BC_COFINS'), CampoNumerico(5, 'ALIQ_COFINS'), @@ -893,7 +972,8 @@ class RegistroC485(Registro): Campo(9, 'COD_ITEM'), Campo(10, 'COD_CTA'), ] - + + nivel = 5 class RegistroC489(Registro): """ @@ -904,7 +984,8 @@ class RegistroC489(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC490(Registro): """ @@ -916,7 +997,8 @@ class RegistroC490(Registro): CampoData(3, 'DT_DOC_FIN', obrigatorio=True), Campo(4, 'COD_MOD', obrigatorio=True), ] - + + nivel = 3 class RegistroC491(Registro): """ @@ -925,8 +1007,8 @@ class RegistroC491(Registro): campos = [ CampoFixo(1, 'REG', 'C491'), Campo(2, 'COD_ITEM'), - Campo(3, 'CST_PIS', obrigatorio=True), - Campo(4, 'CFOP'), + CampoNumerico(3, 'CST_PIS', obrigatorio=True), + CampoNumerico(4, 'CFOP'), CampoNumerico(5, 'VL_ITEM', obrigatorio=True), CampoNumerico(6, 'VL_BC_PIS'), CampoNumerico(7, 'ALIQ_PIS'), @@ -935,7 +1017,8 @@ class RegistroC491(Registro): CampoNumerico(10, 'VL_PIS'), Campo(11, 'COD_CTA'), ] - + + nivel = 4 class RegistroC495(Registro): """ @@ -944,8 +1027,8 @@ class RegistroC495(Registro): campos = [ CampoFixo(1, 'REG', 'C495'), Campo(2, 'COD_ITEM'), - Campo(3, 'CST_COFINS', obrigatorio=True), - Campo(4, 'CFOP'), + CampoNumerico(3, 'CST_COFINS', obrigatorio=True), + CampoNumerico(4, 'CFOP'), CampoNumerico(5, 'VL_ITEM', obrigatorio=True), CampoNumerico(6, 'VL_BC_COFINS'), CampoNumerico(7, 'ALIQ_COFINS'), @@ -954,7 +1037,8 @@ class RegistroC495(Registro): CampoNumerico(10, 'VL_COFINS'), Campo(11, 'COD_CTA'), ] - + + nivel = 4 class RegistroC499(Registro): """ @@ -965,7 +1049,8 @@ class RegistroC499(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC500(Registro): """ @@ -976,10 +1061,10 @@ class RegistroC500(Registro): CampoFixo(1, 'REG', 'C500'), Campo(2, 'COD_PART', obrigatorio=True), Campo(3, 'COD_MOD', obrigatorio=True), - Campo(4, 'COD_SIT', obrigatorio=True), + CampoNumerico(4, 'COD_SIT', obrigatorio=True), Campo(5, 'SER'), - Campo(6, 'SUB'), - Campo(7, 'NUM_DOC', obrigatorio=True), + CampoNumerico(6, 'SUB'), + CampoNumerico(7, 'NUM_DOC', obrigatorio=True), CampoData(8, 'DT_DOC', obrigatorio=True), CampoData(9, 'DT_ENT'), CampoNumerico(10, 'VL_DOC', obrigatorio=True), @@ -988,7 +1073,8 @@ class RegistroC500(Registro): CampoNumerico(13, 'VL_PIS'), CampoNumerico(14, 'VL_COFINS'), ] - + + nivel = 3 class RegistroC501(Registro): """ @@ -996,7 +1082,7 @@ class RegistroC501(Registro): """ campos = [ CampoFixo(1, 'REG', 'C501'), - Campo(2, 'CST_PIS', obrigatorio=True), + CampoNumerico(2, 'CST_PIS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), Campo(4, 'NAT_BC_CRED'), CampoNumerico(5, 'VL_BC_PIS', obrigatorio=True), @@ -1004,7 +1090,8 @@ class RegistroC501(Registro): CampoNumerico(7, 'VL_PIS', obrigatorio=True), Campo(8, 'COD_CTA'), ] - + + nivel = 4 class RegistroC505(Registro): """ @@ -1012,7 +1099,7 @@ class RegistroC505(Registro): """ campos = [ CampoFixo(1, 'REG', 'C505'), - Campo(2, 'CST_COFINS', obrigatorio=True), + CampoNumerico(2, 'CST_COFINS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), Campo(4, 'NAT_BC_CRED'), CampoNumerico(5, 'VL_BC_COFINS', obrigatorio=True), @@ -1020,7 +1107,8 @@ class RegistroC505(Registro): CampoNumerico(7, 'VL_COFINS', obrigatorio=True), Campo(8, 'COD_CTA'), ] - + + nivel = 4 class RegistroC509(Registro): """ @@ -1031,7 +1119,8 @@ class RegistroC509(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC600(Registro): """ @@ -1042,9 +1131,9 @@ class RegistroC600(Registro): campos = [ CampoFixo(1, 'REG', 'C600'), Campo(2, 'COD_MOD', obrigatorio=True), - Campo(3, 'COD_MUN'), + CampoNumerico(3, 'COD_MUN'), Campo(4, 'SER'), - Campo(5, 'SUB'), + CampoNumerico(5, 'SUB'), Campo(6, 'COD_CONS'), CampoNumerico(7, 'QTD_CONS', obrigatorio=True), CampoNumerico(8, 'QTD_CANC'), @@ -1063,7 +1152,8 @@ class RegistroC600(Registro): CampoNumerico(21, 'VL_PIS', obrigatorio=True), CampoNumerico(22, 'VL_COFINS', obrigatorio=True), ] - + + nivel = 3 class RegistroC601(Registro): """ @@ -1071,14 +1161,15 @@ class RegistroC601(Registro): """ campos = [ CampoFixo(1, 'REG', 'C601'), - Campo(2, 'CST_PIS', obrigatorio=True), + CampoNumerico(2, 'CST_PIS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_BC_PIS', obrigatorio=True), CampoNumerico(5, 'ALIQ_PIS', obrigatorio=True), CampoNumerico(6, 'VL_PIS', obrigatorio=True), Campo(7, 'COD_CTA'), ] - + + nivel = 4 class RegistroC605(Registro): """ @@ -1086,14 +1177,15 @@ class RegistroC605(Registro): """ campos = [ CampoFixo(1, 'REG', 'C605'), - Campo(2, 'CST_COFINS', obrigatorio=True), + CampoNumerico(2, 'CST_COFINS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_BC_COFINS', obrigatorio=True), CampoNumerico(5, 'ALIQ_COFINS', obrigatorio=True), CampoNumerico(6, 'VL_COFINS', obrigatorio=True), Campo(7, 'COD_CTA'), ] - + + nivel = 4 class RegistroC609(Registro): """ @@ -1104,7 +1196,8 @@ class RegistroC609(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC800(Registro): """ @@ -1113,15 +1206,15 @@ class RegistroC800(Registro): campos = [ CampoFixo(1, 'REG', 'C800'), Campo(2, 'COD_MOD', obrigatorio=True), - Campo(3, 'COD_SIT', obrigatorio=True), - Campo(4, 'NUM_CFE', obrigatorio=True), + CampoNumerico(3, 'COD_SIT', obrigatorio=True), + CampoNumerico(4, 'NUM_CFE', obrigatorio=True), CampoData(5, 'DT_DOC', obrigatorio=True), CampoNumerico(6, 'VL_CFE', obrigatorio=True), CampoNumerico(7, 'VL_PIS'), CampoNumerico(8, 'VL_COFINS'), - Campo(9, 'CNPJ_CPF'), - Campo(10, 'NR_SAT'), - Campo(11, 'CHV_CFE'), + CampoCPFouCNPJ(9, 'CNPJ_CPF'), + CampoNumerico(10, 'NR_SAT'), + CampoChaveEletronica(11, 'CHV_CFE'), CampoNumerico(12, 'VL_DESC'), CampoNumerico(13, 'VL_MERC'), CampoNumerico(14, 'VL_OUT_DA'), @@ -1129,7 +1222,8 @@ class RegistroC800(Registro): CampoNumerico(16, 'VL_PIS_ST'), CampoNumerico(17, 'VL_COFINS_ST'), ] - + + nivel = 3 class RegistroC810(Registro): """ @@ -1137,20 +1231,21 @@ class RegistroC810(Registro): """ campos = [ CampoFixo(1, 'REG', 'C810'), - Campo(2, 'CFOP', obrigatorio=True), + CampoNumerico(2, 'CFOP', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), Campo(4, 'COD_ITEM'), - Campo(5, 'CST_PIS', obrigatorio=True), + CampoNumerico(5, 'CST_PIS', obrigatorio=True), CampoNumerico(6, 'VL_BC_PIS'), CampoNumerico(7, 'ALIQ_PIS'), CampoNumerico(8, 'VL_PIS'), - Campo(9, 'CST_COFINS', obrigatorio=True), + CampoNumerico(9, 'CST_COFINS', obrigatorio=True), CampoNumerico(10, 'VL_BC_COFINS'), CampoNumerico(11, 'ALIQ_COFINS'), CampoNumerico(12, 'VL_COFINS'), Campo(13, 'COD_CTA'), ] - + + nivel = 4 class RegistroC820(Registro): """ @@ -1159,20 +1254,21 @@ class RegistroC820(Registro): """ campos = [ CampoFixo(1, 'REG', 'C820'), - Campo(2, 'CFOP', obrigatorio=True), + CampoNumerico(2, 'CFOP', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), Campo(4, 'COD_ITEM'), - Campo(5, 'CST_PIS', obrigatorio=True), + CampoNumerico(5, 'CST_PIS', obrigatorio=True), Campo(6, 'QUANT_BC_PIS'), CampoNumerico(7, 'ALIQ_PIS_QUANT'), CampoNumerico(8, 'VL_PIS'), - Campo(9, 'CST_COFINS', obrigatorio=True), + CampoNumerico(9, 'CST_COFINS', obrigatorio=True), Campo(10, 'QUANT_BC_COFINS'), CampoNumerico(11, 'ALIQ_COFINS_QUANT'), CampoNumerico(12, 'VL_COFINS'), Campo(13, 'COD_CTA'), ] - + + nivel = 4 class RegistroC830(Registro): """ @@ -1183,7 +1279,8 @@ class RegistroC830(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC860(Registro): """ @@ -1192,12 +1289,13 @@ class RegistroC860(Registro): campos = [ CampoFixo(1, 'REG', 'C860'), Campo(2, 'COD_MOD', obrigatorio=True), - Campo(3, 'NR_SAT', obrigatorio=True), + CampoNumerico(3, 'NR_SAT', obrigatorio=True), CampoData(4, 'DT_DOC'), Campo(5, 'DOC_INI'), Campo(6, 'DOC_FIM'), ] - + + nivel = 3 class RegistroC870(Registro): """ @@ -1205,20 +1303,21 @@ class RegistroC870(Registro): """ campos = [ CampoFixo(1, 'REG', 'C870'), - Campo(2, 'CFOP', obrigatorio=True), + CampoNumerico(2, 'CFOP', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), Campo(4, 'COD_ITEM'), - Campo(5, 'CST_PIS', obrigatorio=True), + CampoNumerico(5, 'CST_PIS', obrigatorio=True), CampoNumerico(6, 'VL_BC_PIS'), CampoNumerico(7, 'ALIQ_PIS'), CampoNumerico(8, 'VL_PIS'), - Campo(9, 'CST_COFINS', obrigatorio=True), + CampoNumerico(9, 'CST_COFINS', obrigatorio=True), CampoNumerico(10, 'VL_BC_COFINS'), CampoNumerico(11, 'ALIQ_COFINS'), CampoNumerico(12, 'VL_COFINS'), Campo(13, 'COD_CTA'), ] - + + nivel = 4 class RegistroC880(Registro): """ @@ -1227,19 +1326,20 @@ class RegistroC880(Registro): campos = [ CampoFixo(1, 'REG', 'C880'), Campo(2, 'COD_ITEM'), - Campo(3, 'CFOP', obrigatorio=True), + CampoNumerico(3, 'CFOP', obrigatorio=True), CampoNumerico(4, 'VL_ITEM', obrigatorio=True), - Campo(5, 'CST_PIS', obrigatorio=True), + CampoNumerico(5, 'CST_PIS', obrigatorio=True), Campo(6, 'QUANT_BC_PIS'), CampoNumerico(7, 'ALIQ_PIS_QUANT'), CampoNumerico(8, 'VL_PIS'), - Campo(9, 'CST_COFINS', obrigatorio=True), + CampoNumerico(9, 'CST_COFINS', obrigatorio=True), Campo(10, 'QUANT_BC_COFINS'), CampoNumerico(11, 'ALIQ_COFINS_QUANT'), CampoNumerico(12, 'VL_COFINS'), Campo(13, 'COD_CTA'), ] - + + nivel = 4 class RegistroC890(Registro): """ @@ -1250,7 +1350,8 @@ class RegistroC890(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroC990(Registro): """ @@ -1260,7 +1361,8 @@ class RegistroC990(Registro): CampoFixo(1, 'REG', 'C990'), CampoNumerico(2, 'QTD_LIN_C', obrigatorio=True), ] - + + nivel = 1 class RegistroD001(Registro): """ @@ -1270,7 +1372,8 @@ class RegistroD001(Registro): CampoFixo(1, 'REG', 'D001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + + nivel = 1 class RegistroD010(Registro): """ @@ -1280,7 +1383,8 @@ class RegistroD010(Registro): CampoFixo(1, 'REG', 'D010'), CampoCNPJ(2, 'CNPJ', obrigatorio=True), ] - + + nivel = 2 class RegistroD100(Registro): """ @@ -1292,15 +1396,15 @@ class RegistroD100(Registro): Campo(3, 'IND_EMIT', obrigatorio=True), Campo(4, 'COD_PART', obrigatorio=True), Campo(5, 'COD_MOD', obrigatorio=True), - Campo(6, 'COD_SIT', obrigatorio=True), + CampoNumerico(6, 'COD_SIT', obrigatorio=True), Campo(7, 'SER'), - Campo(8, 'SUB'), - Campo(9, 'NUM_DOC', obrigatorio=True), - Campo(10, 'CHV_CTE'), + CampoNumerico(8, 'SUB'), + CampoNumerico(9, 'NUM_DOC', obrigatorio=True), + CampoChaveEletronica(10, 'CHV_CTE'), CampoData(11, 'DT_DOC', obrigatorio=True), CampoData(12, 'DT_A_P'), Campo(13, 'TP_CT-e'), - Campo(14, 'CHV_CTE_REF'), + CampoChaveEletronica(14, 'CHV_CTE_REF'), CampoNumerico(15, 'VL_DOC', obrigatorio=True), CampoNumerico(16, 'VL_DESC'), Campo(17, 'IND_FRT', obrigatorio=True), @@ -1311,7 +1415,8 @@ class RegistroD100(Registro): Campo(22, 'COD_INF'), Campo(23, 'COD_CTA'), ] - + + nivel = 3 class RegistroD101(Registro): """ @@ -1321,14 +1426,15 @@ class RegistroD101(Registro): CampoFixo(1, 'REG', 'D101'), Campo(2, 'IND_NAT_FRT', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), - Campo(4, 'CST_PIS', obrigatorio=True), + CampoNumerico(4, 'CST_PIS', obrigatorio=True), Campo(5, 'NAT_BC_CRED'), CampoNumerico(6, 'VL_BC_PIS'), CampoNumerico(7, 'ALIQ_PIS'), CampoNumerico(8, 'VL_PIS'), Campo(9, 'COD_CTA'), ] - + + nivel = 4 class RegistroD105(Registro): """ @@ -1338,14 +1444,15 @@ class RegistroD105(Registro): CampoFixo(1, 'REG', 'D105'), Campo(2, 'IND_NAT_FRT', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), - Campo(4, 'CST_COFINS', obrigatorio=True), + CampoNumerico(4, 'CST_COFINS', obrigatorio=True), Campo(5, 'NAT_BC_CRED'), CampoNumerico(6, 'VL_BC_COFINS'), CampoNumerico(7, 'ALIQ_COFINS'), CampoNumerico(8, 'VL_COFINS'), Campo(9, 'COD_CTA'), ] - + + nivel = 4 class RegistroD111(Registro): """ @@ -1356,7 +1463,8 @@ class RegistroD111(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroD200(Registro): """ @@ -1365,17 +1473,18 @@ class RegistroD200(Registro): campos = [ CampoFixo(1, 'REG', 'D200'), Campo(2, 'COD_MOD', obrigatorio=True), - Campo(3, 'COD_SIT', obrigatorio=True), + CampoNumerico(3, 'COD_SIT', obrigatorio=True), Campo(4, 'SER'), - Campo(5, 'SUB'), - Campo(6, 'NUM_DOC_INI', obrigatorio=True), - Campo(7, 'NUM_DOC_FIN', obrigatorio=True), - Campo(8, 'CFOP', obrigatorio=True), + CampoNumerico(5, 'SUB'), + CampoNumerico(6, 'NUM_DOC_INI', obrigatorio=True), + CampoNumerico(7, 'NUM_DOC_FIN', obrigatorio=True), + CampoNumerico(8, 'CFOP', obrigatorio=True), CampoData(9, 'DT_REF', obrigatorio=True), CampoNumerico(10, 'VL_DOC', obrigatorio=True), CampoNumerico(11, 'VL_DESC'), ] - + + nivel = 3 class RegistroD201(Registro): """ @@ -1383,14 +1492,15 @@ class RegistroD201(Registro): """ campos = [ CampoFixo(1, 'REG', 'D201'), - Campo(2, 'CST_PIS', obrigatorio=True), + CampoNumerico(2, 'CST_PIS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_BC_PIS'), CampoNumerico(5, 'ALIQ_PIS'), CampoNumerico(6, 'VL_PIS'), Campo(7, 'COD_CTA'), ] - + + nivel = 4 class RegistroD205(Registro): """ @@ -1398,14 +1508,15 @@ class RegistroD205(Registro): """ campos = [ CampoFixo(1, 'REG', 'D205'), - Campo(2, 'CST_COFINS', obrigatorio=True), + CampoNumerico(2, 'CST_COFINS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_BC_COFINS'), CampoNumerico(5, 'ALIQ_COFINS'), CampoNumerico(6, 'VL_COFINS'), Campo(7, 'COD_CTA'), ] - + + nivel = 4 class RegistroD209(Registro): """ @@ -1416,7 +1527,8 @@ class RegistroD209(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroD300(Registro): """ @@ -1426,24 +1538,25 @@ class RegistroD300(Registro): CampoFixo(1, 'REG', 'D300'), Campo(2, 'COD_MOD', obrigatorio=True), Campo(3, 'SER'), - Campo(4, 'SUB'), - Campo(5, 'NUM_DOC_INI'), - Campo(6, 'NUM_DOC_FIN'), - Campo(7, 'CFOP', obrigatorio=True), + CampoNumerico(4, 'SUB'), + CampoNumerico(5, 'NUM_DOC_INI'), + CampoNumerico(6, 'NUM_DOC_FIN'), + CampoNumerico(7, 'CFOP', obrigatorio=True), CampoData(8, 'DT_REF', obrigatorio=True), CampoNumerico(9, 'VL_DOC', obrigatorio=True), CampoNumerico(10, 'VL_DESC'), - Campo(11, 'CST_PIS', obrigatorio=True), + CampoNumerico(11, 'CST_PIS', obrigatorio=True), CampoNumerico(12, 'VL_BC_PIS'), CampoNumerico(13, 'ALIQ_PIS'), CampoNumerico(14, 'VL_PIS'), - Campo(15, 'CST_COFINS', obrigatorio=True), + CampoNumerico(15, 'CST_COFINS', obrigatorio=True), CampoNumerico(16, 'VL_BC_COFINS'), CampoNumerico(17, 'ALIQ_COFINS'), CampoNumerico(18, 'VL_COFINS'), Campo(19, 'COD_CTA'), ] - + + nivel = 3 class RegistroD309(Registro): """ @@ -1454,7 +1567,8 @@ class RegistroD309(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroD350(Registro): """ @@ -1471,13 +1585,13 @@ class RegistroD350(Registro): Campo(8, 'NUM_COO_FIN', obrigatorio=True), Campo(9, 'GT_FIN', obrigatorio=True), CampoNumerico(10, 'VL_BRT', obrigatorio=True), - Campo(11, 'CST_PIS', obrigatorio=True), + CampoNumerico(11, 'CST_PIS', obrigatorio=True), CampoNumerico(12, 'VL_BC_PIS'), CampoNumerico(13, 'ALIQ_PIS'), Campo(14, 'QUANT_BC_PIS'), CampoNumerico(15, 'ALIQ_PIS_QUANT'), CampoNumerico(16, 'VL_PIS'), - Campo(17, 'CST_COFINS', obrigatorio=True), + CampoNumerico(17, 'CST_COFINS', obrigatorio=True), CampoNumerico(18, 'VL_BC_COFINS'), CampoNumerico(19, 'ALIQ_COFINS'), Campo(20, 'QUANT_BC_COFINS'), @@ -1485,7 +1599,8 @@ class RegistroD350(Registro): CampoNumerico(22, 'VL_COFINS'), Campo(23, 'COD_CTA'), ] - + + nivel = 3 class RegistroD359(Registro): """ @@ -1496,7 +1611,8 @@ class RegistroD359(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroD500(Registro): """ @@ -1509,10 +1625,10 @@ class RegistroD500(Registro): Campo(3, 'IND_EMIT', obrigatorio=True), Campo(4, 'COD_PART', obrigatorio=True), Campo(5, 'COD_MOD', obrigatorio=True), - Campo(6, 'COD_SIT', obrigatorio=True), + CampoNumerico(6, 'COD_SIT', obrigatorio=True), Campo(7, 'SER'), - Campo(8, 'SUB'), - Campo(9, 'NUM_DOC', obrigatorio=True), + CampoNumerico(8, 'SUB'), + CampoNumerico(9, 'NUM_DOC', obrigatorio=True), CampoData(10, 'DT_DOC', obrigatorio=True), CampoData(11, 'DT_A_P', obrigatorio=True), CampoNumerico(12, 'VL_DOC', obrigatorio=True), @@ -1527,7 +1643,8 @@ class RegistroD500(Registro): CampoNumerico(21, 'VL_PIS'), CampoNumerico(22, 'VL_COFINS'), ] - + + nivel = 3 class RegistroD501(Registro): """ @@ -1535,7 +1652,7 @@ class RegistroD501(Registro): """ campos = [ CampoFixo(1, 'REG', 'D501'), - Campo(2, 'CST_PIS', obrigatorio=True), + CampoNumerico(2, 'CST_PIS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), Campo(4, 'NAT_BC_CRED'), CampoNumerico(5, 'VL_BC_PIS'), @@ -1543,7 +1660,8 @@ class RegistroD501(Registro): CampoNumerico(7, 'VL_PIS'), Campo(8, 'COD_CTA'), ] - + + nivel = 4 class RegistroD505(Registro): """ @@ -1551,7 +1669,7 @@ class RegistroD505(Registro): """ campos = [ CampoFixo(1, 'REG', 'D505'), - Campo(2, 'CST_COFINS', obrigatorio=True), + CampoNumerico(2, 'CST_COFINS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), Campo(4, 'NAT_BC_CRED'), CampoNumerico(5, 'VL_BC_COFINS'), @@ -1559,7 +1677,8 @@ class RegistroD505(Registro): CampoNumerico(7, 'VL_COFINS'), Campo(8, 'COD_CTA'), ] - + + nivel = 4 class RegistroD509(Registro): """ @@ -1570,7 +1689,8 @@ class RegistroD509(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroD600(Registro): """ @@ -1580,9 +1700,9 @@ class RegistroD600(Registro): campos = [ CampoFixo(1, 'REG', 'D600'), Campo(2, 'COD_MOD', obrigatorio=True), - Campo(3, 'COD_MUN'), + CampoNumerico(3, 'COD_MUN'), Campo(4, 'SER'), - Campo(5, 'SUB'), + CampoNumerico(5, 'SUB'), Campo(6, 'IND_REC', obrigatorio=True), CampoNumerico(7, 'QTD_CONS', obrigatorio=True), CampoData(8, 'DT_DOC_INI', obrigatorio=True), @@ -1598,7 +1718,8 @@ class RegistroD600(Registro): CampoNumerico(18, 'VL_PIS'), CampoNumerico(19, 'VL_COFINS'), ] - + + nivel = 3 class RegistroD601(Registro): """ @@ -1609,13 +1730,14 @@ class RegistroD601(Registro): Campo(2, 'COD_CLASS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_DESC'), - Campo(5, 'CST_PIS', obrigatorio=True), + CampoNumerico(5, 'CST_PIS', obrigatorio=True), CampoNumerico(6, 'VL_BC_PIS'), CampoNumerico(7, 'ALIQ_PIS'), CampoNumerico(8, 'VL_PIS'), Campo(9, 'COD_CTA'), ] - + + nivel = 4 class RegistroD605(Registro): """ @@ -1626,13 +1748,14 @@ class RegistroD605(Registro): Campo(2, 'COD_CLASS', obrigatorio=True), CampoNumerico(3, 'VL_ITEM', obrigatorio=True), CampoNumerico(4, 'VL_DESC'), - Campo(5, 'CST_COFINS', obrigatorio=True), + CampoNumerico(5, 'CST_COFINS', obrigatorio=True), CampoNumerico(6, 'VL_BC_COFINS'), CampoNumerico(7, 'ALIQ_COFINS'), CampoNumerico(8, 'VL_COFINS'), Campo(9, 'COD_CTA'), ] - + + nivel = 4 class RegistroD609(Registro): """ @@ -1643,7 +1766,8 @@ class RegistroD609(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroD990(Registro): """ @@ -1653,7 +1777,8 @@ class RegistroD990(Registro): CampoFixo(1, 'REG', 'D990'), CampoNumerico(2, 'QTD_LIN_D', obrigatorio=True), ] - + + nivel = 1 class RegistroF001(Registro): """ @@ -1663,7 +1788,8 @@ class RegistroF001(Registro): CampoFixo(1, 'REG', 'F001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + + nivel = 1 class RegistroF010(Registro): """ @@ -1673,7 +1799,8 @@ class RegistroF010(Registro): CampoFixo(1, 'REG', 'F010'), CampoCNPJ(2, 'CNPJ', obrigatorio=True), ] - + + nivel = 2 class RegistroF100(Registro): """ @@ -1686,11 +1813,11 @@ class RegistroF100(Registro): Campo(4, 'COD_ITEM'), CampoData(5, 'DT_OPER', obrigatorio=True), CampoNumerico(6, 'VL_OPER', obrigatorio=True), - Campo(7, 'CST_PIS', obrigatorio=True), + CampoNumerico(7, 'CST_PIS', obrigatorio=True), CampoNumerico(8, 'VL_BC_PIS'), CampoNumerico(9, 'ALIQ_PIS'), CampoNumerico(10, 'VL_PIS'), - Campo(11, 'CST_COFINS', obrigatorio=True), + CampoNumerico(11, 'CST_COFINS', obrigatorio=True), CampoNumerico(12, 'VL_BC_COFINS'), CampoNumerico(13, 'ALIQ_COFINS'), CampoNumerico(14, 'VL_COFINS'), @@ -1700,7 +1827,8 @@ class RegistroF100(Registro): Campo(18, 'COD_CCUS'), Campo(19, 'DESC_DOC_OPER'), ] - + + nivel = 3 class RegistroF111(Registro): """ @@ -1711,7 +1839,8 @@ class RegistroF111(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroF120(Registro): """ @@ -1726,11 +1855,11 @@ class RegistroF120(Registro): Campo(5, 'IND_UTIL_BEM_IMOB', obrigatorio=True), CampoNumerico(6, 'VL_OPER_DEP', obrigatorio=True), Campo(7, 'PARC_OPER_NAO_BC_CRED'), - Campo(8, 'CST_PIS', obrigatorio=True), + CampoNumerico(8, 'CST_PIS', obrigatorio=True), CampoNumerico(9, 'VL_BC_PIS'), CampoNumerico(10, 'ALIQ_PIS'), CampoNumerico(11, 'VL_PIS'), - Campo(12, 'CST_COFINS', obrigatorio=True), + CampoNumerico(12, 'CST_COFINS', obrigatorio=True), CampoNumerico(13, 'VL_BC_COFINS'), CampoNumerico(14, 'ALIQ_COFINS'), CampoNumerico(15, 'VL_COFINS'), @@ -1738,7 +1867,8 @@ class RegistroF120(Registro): Campo(17, 'COD_CCUS'), Campo(18, 'DESC_BEM_IMOB'), ] - + + nivel = 3 class RegistroF129(Registro): """ @@ -1749,7 +1879,8 @@ class RegistroF129(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroF130(Registro): """ @@ -1766,11 +1897,11 @@ class RegistroF130(Registro): Campo(8, 'PARC_OPER_NAO_BC_CRED'), CampoNumerico(9, 'VL_BC_CRED', obrigatorio=True), Campo(10, 'IND_NR_PARC', obrigatorio=True), - Campo(11, 'CST_PIS', obrigatorio=True), + CampoNumerico(11, 'CST_PIS', obrigatorio=True), CampoNumerico(12, 'VL_BC_PIS'), CampoNumerico(13, 'ALIQ_PIS'), CampoNumerico(14, 'VL_PIS'), - Campo(15, 'CST_COFINS', obrigatorio=True), + CampoNumerico(15, 'CST_COFINS', obrigatorio=True), CampoNumerico(16, 'VL_BC_COFINS'), CampoNumerico(17, 'ALIQ_COFINS'), CampoNumerico(18, 'VL_COFINS'), @@ -1778,7 +1909,8 @@ class RegistroF130(Registro): Campo(20, 'COD_CCUS'), Campo(21, 'DESC_BEM_IMOB'), ] - + + nivel = 3 class RegistroF139(Registro): """ @@ -1789,7 +1921,8 @@ class RegistroF139(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroF150(Registro): """ @@ -1802,16 +1935,17 @@ class RegistroF150(Registro): Campo(4, 'EST_IMP'), CampoNumerico(5, 'VL_BC_EST', obrigatorio=True), CampoNumerico(6, 'VL_BC_MEN_EST', obrigatorio=True), - Campo(7, 'CST_PIS', obrigatorio=True), + CampoNumerico(7, 'CST_PIS', obrigatorio=True), CampoNumerico(8, 'ALIQ_PIS', obrigatorio=True), CampoNumerico(9, 'VL_CRED_PIS', obrigatorio=True), - Campo(10, 'CST_COFINS', obrigatorio=True), + CampoNumerico(10, 'CST_COFINS', obrigatorio=True), CampoNumerico(11, 'ALIQ_COFINS', obrigatorio=True), CampoNumerico(12, 'VL_CRED_COFINS', obrigatorio=True), Campo(13, 'DESC_EST'), Campo(14, 'COD_CTA'), ] - + + nivel = 3 class RegistroF200(Registro): """ @@ -1829,11 +1963,11 @@ class RegistroF200(Registro): CampoNumerico(9, 'VL_TOT_VEND', obrigatorio=True), CampoNumerico(10, 'VL_REC_ACUM'), CampoNumerico(11, 'VL_TOT_REC', obrigatorio=True), - Campo(12, 'CST_PIS', obrigatorio=True), + CampoNumerico(12, 'CST_PIS', obrigatorio=True), CampoNumerico(13, 'VL_BC_PIS'), CampoNumerico(14, 'ALIQ_PIS'), CampoNumerico(15, 'VL_PIS'), - Campo(16, 'CST_COFINS', obrigatorio=True), + CampoNumerico(16, 'CST_COFINS', obrigatorio=True), CampoNumerico(17, 'VL_BC_COFINS'), CampoNumerico(18, 'ALIQ_COFINS'), CampoNumerico(19, 'VL_COFINS'), @@ -1841,7 +1975,8 @@ class RegistroF200(Registro): Campo(21, 'IND_NAT_EMP'), Campo(22, 'INF_COMP'), ] - + + nivel = 3 class RegistroF205(Registro): """ @@ -1854,20 +1989,21 @@ class RegistroF205(Registro): CampoNumerico(4, 'VL_CUS_INC_ACUM', obrigatorio=True), CampoNumerico(5, 'VL_EXC_BC_CUS_INC_ACUM', obrigatorio=True), CampoNumerico(6, 'VL_BC_CUS_INC', obrigatorio=True), - Campo(7, 'CST_PIS', obrigatorio=True), + CampoNumerico(7, 'CST_PIS', obrigatorio=True), CampoNumerico(8, 'ALIQ_PIS', obrigatorio=True), CampoNumerico(9, 'VL_CRED_PIS_ACUM', obrigatorio=True), CampoNumerico(10, 'VL_CRED_PIS_DESC_ANT', obrigatorio=True), CampoNumerico(11, 'VL_CRED_PIS_DESC', obrigatorio=True), CampoNumerico(12, 'VL_CRED_PIS_DESC_FUT', obrigatorio=True), - Campo(13, 'CST_COFINS', obrigatorio=True), + CampoNumerico(13, 'CST_COFINS', obrigatorio=True), CampoNumerico(14, 'ALIQ_COFINS', obrigatorio=True), CampoNumerico(15, 'VL_CRED_COFINS_ACUM', obrigatorio=True), CampoNumerico(16, 'VL_CRED_COFINS_DESC_ANT', obrigatorio=True), CampoNumerico(17, 'VL_CRED_COFINS_DESC', obrigatorio=True), CampoNumerico(18, 'VL_CRED_COFINS_DESC_FUT', obrigatorio=True), ] - + + nivel = 4 class RegistroF210(Registro): """ @@ -1879,14 +2015,15 @@ class RegistroF210(Registro): CampoNumerico(3, 'VL_EXC', obrigatorio=True), CampoNumerico(4, 'VL_CUS_ORC_AJU', obrigatorio=True), CampoNumerico(5, 'VL_BC_CRED', obrigatorio=True), - Campo(6, 'CST_PIS', obrigatorio=True), + CampoNumerico(6, 'CST_PIS', obrigatorio=True), CampoNumerico(7, 'ALIQ_PIS'), CampoNumerico(8, 'VL_CRED_PIS_UTIL'), - Campo(9, 'CST_COFINS', obrigatorio=True), + CampoNumerico(9, 'CST_COFINS', obrigatorio=True), CampoNumerico(10, 'ALIQ_COFINS'), CampoNumerico(11, 'VL_CRED_COFINS_UTIL'), ] - + + nivel = 4 class RegistroF211(Registro): """ @@ -1897,7 +2034,8 @@ class RegistroF211(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroF500(Registro): """ @@ -1907,22 +2045,23 @@ class RegistroF500(Registro): campos = [ CampoFixo(1, 'REG', 'F500'), CampoNumerico(2, 'VL_REC_CAIXA', obrigatorio=True), - Campo(3, 'CST_PIS', obrigatorio=True), + CampoNumerico(3, 'CST_PIS', obrigatorio=True), CampoNumerico(4, 'VL_DESC_PIS'), CampoNumerico(5, 'VL_BC_PIS'), CampoNumerico(6, 'ALIQ_PIS'), CampoNumerico(7, 'VL_PIS'), - Campo(8, 'CST_COFINS', obrigatorio=True), + CampoNumerico(8, 'CST_COFINS', obrigatorio=True), CampoNumerico(9, 'VL_DESC_COFINS'), CampoNumerico(10, 'VL_BC_COFINS'), CampoNumerico(11, 'ALIQ_COFINS'), CampoNumerico(12, 'VL_COFINS'), Campo(13, 'COD_MOD'), - Campo(14, 'CFOP'), + CampoNumerico(14, 'CFOP'), Campo(15, 'COD_CTA'), Campo(16, 'INFO_COMPL'), ] - + + nivel = 3 class RegistroF509(Registro): """ @@ -1933,7 +2072,8 @@ class RegistroF509(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroF510(Registro): """ @@ -1943,22 +2083,23 @@ class RegistroF510(Registro): campos = [ CampoFixo(1, 'REG', 'F510'), CampoNumerico(2, 'VL_REC_CAIXA', obrigatorio=True), - Campo(3, 'CST_PIS', obrigatorio=True), + CampoNumerico(3, 'CST_PIS', obrigatorio=True), CampoNumerico(4, 'VL_DESC_PIS'), Campo(5, 'QUANT_BC_PIS'), CampoNumerico(6, 'ALIQ_PIS_QUANT'), CampoNumerico(7, 'VL_PIS'), - Campo(8, 'CST_COFINS', obrigatorio=True), + CampoNumerico(8, 'CST_COFINS', obrigatorio=True), CampoNumerico(9, 'VL_DESC_COFINS'), Campo(10, 'QUANT_BC_COFINS'), CampoNumerico(11, 'ALIQ_COFINS_QUANT'), CampoNumerico(12, 'VL_COFINS'), Campo(13, 'COD_MOD'), - Campo(14, 'CFOP'), + CampoNumerico(14, 'CFOP'), Campo(15, 'COD_CTA'), Campo(16, 'INFO_COMPL'), ] - + + nivel = 3 class RegistroF519(Registro): """ @@ -1969,7 +2110,8 @@ class RegistroF519(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroF525(Registro): """ @@ -1979,16 +2121,17 @@ class RegistroF525(Registro): CampoFixo(1, 'REG', 'F525'), CampoNumerico(2, 'VL_REC', obrigatorio=True), Campo(3, 'IND_REC', obrigatorio=True), - Campo(4, 'CNPJ_CPF'), - Campo(5, 'NUM_DOC'), + CampoCPFouCNPJ(4, 'CNPJ_CPF'), + CampoNumerico(5, 'NUM_DOC'), Campo(6, 'COD_ITEM'), CampoNumerico(7, 'VL_REC_DET', obrigatorio=True), - Campo(8, 'CST_PIS'), - Campo(9, 'CST_COFINS'), + CampoNumerico(8, 'CST_PIS'), + CampoNumerico(9, 'CST_COFINS'), Campo(10, 'INFO_COMPL'), Campo(11, 'COD_CTA'), ] - + + nivel = 3 class RegistroF550(Registro): """ @@ -1998,22 +2141,23 @@ class RegistroF550(Registro): campos = [ CampoFixo(1, 'REG', 'F550'), CampoNumerico(2, 'VL_REC_COMP', obrigatorio=True), - Campo(3, 'CST_PIS', obrigatorio=True), + CampoNumerico(3, 'CST_PIS', obrigatorio=True), CampoNumerico(4, 'VL_DESC_PIS'), CampoNumerico(5, 'VL_BC_PIS'), CampoNumerico(6, 'ALIQ_PIS'), CampoNumerico(7, 'VL_PIS'), - Campo(8, 'CST_COFINS', obrigatorio=True), + CampoNumerico(8, 'CST_COFINS', obrigatorio=True), CampoNumerico(9, 'VL_DESC_COFINS'), CampoNumerico(10, 'VL_BC_COFINS'), CampoNumerico(11, 'ALIQ_COFINS'), CampoNumerico(12, 'VL_COFINS'), Campo(13, 'COD_MOD'), - Campo(14, 'CFOP'), + CampoNumerico(14, 'CFOP'), Campo(15, 'COD_CTA'), Campo(16, 'INFO_COMPL'), ] - + + nivel = 3 class RegistroF559(Registro): """ @@ -2024,7 +2168,8 @@ class RegistroF559(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroF560(Registro): """ @@ -2035,22 +2180,23 @@ class RegistroF560(Registro): campos = [ CampoFixo(1, 'REG', 'F560'), CampoNumerico(2, 'VL_REC_COMP', obrigatorio=True), - Campo(3, 'CST_PIS', obrigatorio=True), + CampoNumerico(3, 'CST_PIS', obrigatorio=True), CampoNumerico(4, 'VL_DESC_PIS'), Campo(5, 'QUANT_BC_PIS'), CampoNumerico(6, 'ALIQ_PIS_QUANT'), CampoNumerico(7, 'VL_PIS'), - Campo(8, 'CST_COFINS', obrigatorio=True), + CampoNumerico(8, 'CST_COFINS', obrigatorio=True), CampoNumerico(9, 'VL_DESC_COFINS'), Campo(10, 'QUANT_BC_COFINS'), CampoNumerico(11, 'ALIQ_COFINS_QUANT'), CampoNumerico(12, 'VL_COFINS'), Campo(13, 'COD_MOD'), - Campo(14, 'CFOP'), + CampoNumerico(14, 'CFOP'), Campo(15, 'COD_CTA'), Campo(16, 'INFO_COMPL'), ] - + + nivel = 3 class RegistroF569(Registro): """ @@ -2061,7 +2207,8 @@ class RegistroF569(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroF600(Registro): """ @@ -2080,7 +2227,8 @@ class RegistroF600(Registro): CampoNumerico(10, 'VL_RET_COFINS', obrigatorio=True), Campo(11, 'IND_DEC', obrigatorio=True), ] - + + nivel = 3 class RegistroF700(Registro): """ @@ -2096,7 +2244,8 @@ class RegistroF700(Registro): CampoCNPJ(7, 'CNPJ'), Campo(8, 'INF_COMP'), ] - + + nivel = 3 class RegistroF800(Registro): """ @@ -2113,7 +2262,8 @@ class RegistroF800(Registro): CampoNumerico(8, 'VL_CRED_COFINS', obrigatorio=True), Campo(9, 'PER_CRED_CIS'), ] - + + nivel = 3 class RegistroF990(Registro): """ @@ -2123,7 +2273,8 @@ class RegistroF990(Registro): CampoFixo(1, 'REG', 'F990'), CampoNumerico(2, 'QTD_LIN_F', obrigatorio=True), ] - + + nivel = 1 class RegistroI001(Registro): """ @@ -2133,7 +2284,8 @@ class RegistroI001(Registro): CampoFixo(1, 'REG', 'I001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + + nivel = 1 class RegistroI010(Registro): """ @@ -2145,7 +2297,8 @@ class RegistroI010(Registro): Campo(3, 'IND_ATIV', obrigatorio=True), Campo(4, 'INFO_COMPL'), ] - + + nivel = 2 class RegistroI100(Registro): """ @@ -2154,7 +2307,7 @@ class RegistroI100(Registro): campos = [ CampoFixo(1, 'REG', 'I100'), CampoNumerico(2, 'VL_REC', obrigatorio=True), - Campo(3, 'CST_PIS_COFINS', obrigatorio=True), + CampoNumerico(3, 'CST_PIS_COFINS', obrigatorio=True), CampoNumerico(4, 'VL_TOT_DED_GER', obrigatorio=True), CampoNumerico(5, 'VL_TOT_DED_ESP', obrigatorio=True), CampoNumerico(6, 'VL_BC_PIS', obrigatorio=True), @@ -2165,7 +2318,8 @@ class RegistroI100(Registro): CampoNumerico(11, 'VL_COFINS', obrigatorio=True), Campo(12, 'INFO_COMPL', obrigatorio=True), ] - + + nivel = 3 class RegistroI199(Registro): """ @@ -2176,7 +2330,8 @@ class RegistroI199(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroI200(Registro): """ @@ -2190,7 +2345,8 @@ class RegistroI200(Registro): Campo(5, 'COD_CTA', obrigatorio=True), Campo(6, 'INFO_COMPL', obrigatorio=True), ] - + + nivel = 4 class RegistroI299(Registro): """ @@ -2201,7 +2357,8 @@ class RegistroI299(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 5 class RegistroI300(Registro): """ @@ -2214,7 +2371,8 @@ class RegistroI300(Registro): Campo(4, 'COD_CTA', obrigatorio=True), Campo(5, 'INFO_COMPL', obrigatorio=True), ] - + + nivel = 5 class RegistroI399(Registro): """ @@ -2225,7 +2383,8 @@ class RegistroI399(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 6 class RegistroI990(Registro): """ @@ -2235,7 +2394,8 @@ class RegistroI990(Registro): CampoFixo(1, 'REG', 'I990'), CampoNumerico(2, 'QTD_LIN_I', obrigatorio=True), ] - + + nivel = 1 class RegistroM001(Registro): """ @@ -2245,7 +2405,7 @@ class RegistroM001(Registro): CampoFixo(1, 'REG', 'M001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + nivel = 1 class RegistroM100(Registro): """ @@ -2268,7 +2428,8 @@ class RegistroM100(Registro): CampoNumerico(14, 'VL_CRED_DESC'), Campo(15, 'SLD_CRED', obrigatorio=True), ] - + + nivel = 2 class RegistroM105(Registro): """ @@ -2277,7 +2438,7 @@ class RegistroM105(Registro): campos = [ CampoFixo(1, 'REG', 'M105'), Campo(2, 'NAT_BC_CRED', obrigatorio=True), - Campo(3, 'CST_PIS', obrigatorio=True), + CampoNumerico(3, 'CST_PIS', obrigatorio=True), CampoNumerico(4, 'VL_BC_PIS_TOT'), CampoNumerico(5, 'VL_BC_PIS_CUM'), CampoNumerico(6, 'VL_BC_PIS_NC'), @@ -2286,7 +2447,8 @@ class RegistroM105(Registro): Campo(9, 'QUANT_BC_PIS'), Campo(10, 'DESC_CRED'), ] - + + nivel = 3 class RegistroM110(Registro): """ @@ -2297,11 +2459,12 @@ class RegistroM110(Registro): Campo(2, 'IND_AJ', obrigatorio=True), CampoNumerico(3, 'VL_AJ', obrigatorio=True), Campo(4, 'COD_AJ', obrigatorio=True), - Campo(5, 'NUM_DOC'), + CampoNumerico(5, 'NUM_DOC'), Campo(6, 'DESCR_AJ'), CampoData(7, 'DT_REF'), ] - + + nivel = 3 class RegistroM115(Registro): """ @@ -2310,7 +2473,7 @@ class RegistroM115(Registro): campos = [ CampoFixo(1, 'REG', 'M115'), Campo(2, 'DET_VALOR_AJ', obrigatorio=True), - Campo(3, 'CST_PIS'), + CampoNumerico(3, 'CST_PIS'), Campo(4, 'DET_BC_CRED'), Campo(5, 'DET_ALIQ'), CampoData(6, 'DT_OPER_AJ', obrigatorio=True), @@ -2318,7 +2481,8 @@ class RegistroM115(Registro): Campo(8, 'COD_CTA'), Campo(9, 'INFO_COMPL'), ] - + + nivel = 4 class RegistroM200(Registro): """ @@ -2339,7 +2503,8 @@ class RegistroM200(Registro): CampoNumerico(12, 'VL_CONT_CUM_REC', obrigatorio=True), CampoNumerico(13, 'VL_TOT_CONT_REC', obrigatorio=True), ] - + + nivel = 2 class RegistroM205(Registro): """ @@ -2351,7 +2516,8 @@ class RegistroM205(Registro): Campo(3, 'COD_REC', obrigatorio=True), CampoNumerico(4, 'VL_DEBITO', obrigatorio=True), ] - + + nivel = 3 class RegistroM210(Registro): """ @@ -2372,7 +2538,8 @@ class RegistroM210(Registro): CampoNumerico(12, 'VL_CONT_DIFER_ANT'), CampoNumerico(13, 'VL_CONT_PER', obrigatorio=True), ] - + + nivel = 3 class RegistroM211(Registro): """ @@ -2386,7 +2553,8 @@ class RegistroM211(Registro): CampoNumerico(5, 'VL_EXC_ESP_COOP'), CampoNumerico(6, 'VL_BC_CONT', obrigatorio=True), ] - + + nivel = 4 class RegistroM220(Registro): """ @@ -2397,11 +2565,12 @@ class RegistroM220(Registro): Campo(2, 'IND_AJ', obrigatorio=True), CampoNumerico(3, 'VL_AJ', obrigatorio=True), Campo(4, 'COD_AJ', obrigatorio=True), - Campo(5, 'NUM_DOC'), + CampoNumerico(5, 'NUM_DOC'), Campo(6, 'DESCR_AJ'), CampoData(7, 'DT_REF'), ] - + + nivel = 4 class RegistroM225(Registro): """ @@ -2410,7 +2579,7 @@ class RegistroM225(Registro): campos = [ CampoFixo(1, 'REG', 'M225'), Campo(2, 'DET_VALOR_AJ', obrigatorio=True), - Campo(3, 'CST_PIS'), + CampoNumerico(3, 'CST_PIS'), Campo(4, 'DET_BC_CRED'), Campo(5, 'DET_ALIQ'), CampoData(6, 'DT_OPER_AJ', obrigatorio=True), @@ -2418,7 +2587,8 @@ class RegistroM225(Registro): Campo(8, 'COD_CTA'), Campo(9, 'INFO_COMPL'), ] - + + nivel = 5 class RegistroM230(Registro): """ @@ -2433,7 +2603,8 @@ class RegistroM230(Registro): CampoNumerico(6, 'VL_CRED_DIF'), Campo(7, 'COD_CRED'), ] - + + nivel = 4 class RegistroM300(Registro): """ @@ -2449,7 +2620,8 @@ class RegistroM300(Registro): Campo(7, 'PER_APUR', obrigatorio=True), CampoData(8, 'DT_RECEB'), ] - + + nivel = 2 class RegistroM350(Registro): """ @@ -2463,7 +2635,8 @@ class RegistroM350(Registro): CampoNumerico(5, 'ALIQ_PIS_FOL', obrigatorio=True), CampoNumerico(6, 'VL_TOT_CONT_FOL', obrigatorio=True), ] - + + nivel = 2 class RegistroM400(Registro): """ @@ -2472,12 +2645,13 @@ class RegistroM400(Registro): """ campos = [ CampoFixo(1, 'REG', 'M400'), - Campo(2, 'CST_PIS', obrigatorio=True), + CampoNumerico(2, 'CST_PIS', obrigatorio=True), CampoNumerico(3, 'VL_TOT_REC', obrigatorio=True), Campo(4, 'COD_CTA'), Campo(5, 'DESC_COMPL'), ] - + + nivel = 2 class RegistroM410(Registro): """ @@ -2491,7 +2665,8 @@ class RegistroM410(Registro): Campo(4, 'COD_CTA', obrigatorio=True), Campo(5, 'DESC_COMPL', obrigatorio=True), ] - + + nivel = 3 class RegistroM500(Registro): """ @@ -2514,7 +2689,8 @@ class RegistroM500(Registro): CampoNumerico(14, 'VL_CRED_DESC'), Campo(15, 'SLD_CRED', obrigatorio=True), ] - + + nivel = 2 class RegistroM505(Registro): """ @@ -2523,7 +2699,7 @@ class RegistroM505(Registro): campos = [ CampoFixo(1, 'REG', 'M505'), Campo(2, 'NAT_BC_CRED', obrigatorio=True), - Campo(3, 'CST_COFINS', obrigatorio=True), + CampoNumerico(3, 'CST_COFINS', obrigatorio=True), CampoNumerico(4, 'VL_BC_COFINS_TOT'), CampoNumerico(5, 'VL_BC_COFINS_CUM'), CampoNumerico(6, 'VL_BC_COFINS_NC'), @@ -2532,7 +2708,8 @@ class RegistroM505(Registro): Campo(9, 'QUANT_BC_COFINS'), Campo(10, 'DESC_CRED'), ] - + + nivel = 3 class RegistroM510(Registro): """ @@ -2543,11 +2720,12 @@ class RegistroM510(Registro): Campo(2, 'IND_AJ', obrigatorio=True), CampoNumerico(3, 'VL_AJ', obrigatorio=True), Campo(4, 'COD_AJ', obrigatorio=True), - Campo(5, 'NUM_DOC'), + CampoNumerico(5, 'NUM_DOC'), Campo(6, 'DESCR_AJ'), CampoData(7, 'DT_REF'), ] - + + nivel = 3 class RegistroM515(Registro): """ @@ -2556,7 +2734,7 @@ class RegistroM515(Registro): campos = [ CampoFixo(1, 'REG', 'M515'), Campo(2, 'DET_VALOR_AJ', obrigatorio=True), - Campo(3, 'CST_COFINS', obrigatorio=True), + CampoNumerico(3, 'CST_COFINS', obrigatorio=True), Campo(4, 'DET_BC_CRED'), Campo(5, 'DET_ALIQ'), CampoData(6, 'DT_OPER_AJ', obrigatorio=True), @@ -2564,7 +2742,8 @@ class RegistroM515(Registro): Campo(8, 'COD_CTA'), Campo(9, 'INFO_COMPL'), ] - + + nivel = 4 class RegistroM600(Registro): """ @@ -2585,7 +2764,8 @@ class RegistroM600(Registro): CampoNumerico(12, 'VL_CONT_CUM_REC', obrigatorio=True), CampoNumerico(13, 'VL_TOT_CONT_REC', obrigatorio=True), ] - + + nivel = 2 class RegistroM605(Registro): """ @@ -2597,7 +2777,8 @@ class RegistroM605(Registro): Campo(3, 'COD_REC', obrigatorio=True), CampoNumerico(4, 'VL_DEBITO', obrigatorio=True), ] - + + nivel = 3 class RegistroM610(Registro): """ @@ -2618,7 +2799,8 @@ class RegistroM610(Registro): CampoNumerico(12, 'VL_CONT_DIFER_ANT'), CampoNumerico(13, 'VL_CONT_PER', obrigatorio=True), ] - + + nivel = 3 class RegistroM611(Registro): """ @@ -2632,7 +2814,8 @@ class RegistroM611(Registro): CampoNumerico(5, 'VL_EXC_ESP_COOP'), CampoNumerico(6, 'VL_BC_CONT', obrigatorio=True), ] - + + nivel = 4 class RegistroM620(Registro): """ @@ -2643,11 +2826,12 @@ class RegistroM620(Registro): Campo(2, 'IND_AJ', obrigatorio=True), CampoNumerico(3, 'VL_AJ', obrigatorio=True), Campo(4, 'COD_AJ', obrigatorio=True), - Campo(5, 'NUM_DOC'), + CampoNumerico(5, 'NUM_DOC'), Campo(6, 'DESCR_AJ'), CampoData(7, 'DT_REF'), ] - + + nivel = 4 class RegistroM625(Registro): """ @@ -2656,7 +2840,7 @@ class RegistroM625(Registro): campos = [ CampoFixo(1, 'REG', 'M625'), Campo(2, 'DET_VALOR_AJ', obrigatorio=True), - Campo(3, 'CST_COFINS'), + CampoNumerico(3, 'CST_COFINS'), Campo(4, 'DET_BC_CRED'), Campo(5, 'DET_ALIQ'), CampoData(6, 'DT_OPER_AJ', obrigatorio=True), @@ -2664,7 +2848,8 @@ class RegistroM625(Registro): Campo(8, 'COD_CTA'), Campo(9, 'INFO_COMPL'), ] - + + nivel = 5 class RegistroM630(Registro): """ @@ -2679,7 +2864,8 @@ class RegistroM630(Registro): CampoNumerico(6, 'VL_CRED_DIF'), Campo(7, 'COD_CRED'), ] - + + nivel = 4 class RegistroM700(Registro): """ @@ -2695,7 +2881,8 @@ class RegistroM700(Registro): Campo(7, 'PER_APUR', obrigatorio=True), CampoData(8, 'DT_RECEB'), ] - + + nivel = 2 class RegistroM800(Registro): """ @@ -2704,12 +2891,13 @@ class RegistroM800(Registro): """ campos = [ CampoFixo(1, 'REG', 'M800'), - Campo(2, 'CST_COFINS', obrigatorio=True), + CampoNumerico(2, 'CST_COFINS', obrigatorio=True), CampoNumerico(3, 'VL_TOT_REC', obrigatorio=True), Campo(4, 'COD_CTA'), Campo(5, 'DESC_COMPL'), ] - + + nivel = 2 class RegistroM810(Registro): """ @@ -2723,7 +2911,8 @@ class RegistroM810(Registro): Campo(4, 'COD_CTA'), Campo(5, 'DESC_COMPL'), ] - + + nivel = 3 class RegistroM990(Registro): """ @@ -2733,7 +2922,8 @@ class RegistroM990(Registro): CampoFixo(1, 'REG', 'M990'), CampoNumerico(2, 'QTD_LIN_M', obrigatorio=True), ] - + + nivel = 1 class RegistroP001(Registro): """ @@ -2743,7 +2933,8 @@ class RegistroP001(Registro): CampoFixo(1, 'REG', 'P001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + + nivel = 1 class RegistroP010(Registro): """ @@ -2753,7 +2944,8 @@ class RegistroP010(Registro): CampoFixo(1, 'REG', 'P010'), CampoCNPJ(2, 'CNPJ', obrigatorio=True), ] - + + nivel = 2 class RegistroP100(Registro): """ @@ -2773,7 +2965,8 @@ class RegistroP100(Registro): Campo(11, 'COD_CTA'), Campo(12, 'INFO_COMPL'), ] - + + nivel = 3 class RegistroP110(Registro): """ @@ -2786,7 +2979,8 @@ class RegistroP110(Registro): Campo(4, 'DET_VALOR', obrigatorio=True), Campo(5, 'INF_COMPL'), ] - + + nivel = 4 class RegistroP199(Registro): """ @@ -2797,7 +2991,8 @@ class RegistroP199(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 4 class RegistroP200(Registro): """ @@ -2812,7 +3007,8 @@ class RegistroP200(Registro): CampoNumerico(6, 'VL_TOT_CONT_DEV', obrigatorio=True), Campo(7, 'COD_REC', obrigatorio=True), ] - + + nivel = 2 class RegistroP210(Registro): """ @@ -2823,11 +3019,12 @@ class RegistroP210(Registro): Campo(2, 'IND_AJ', obrigatorio=True), CampoNumerico(3, 'VL_AJ', obrigatorio=True), Campo(4, 'COD_AJ', obrigatorio=True), - Campo(5, 'NUM_DOC'), + CampoNumerico(5, 'NUM_DOC'), Campo(6, 'DESCR_AJ'), CampoData(7, 'DT_REF'), ] - + + nivel = 3 class RegistroP990(Registro): """ @@ -2837,7 +3034,8 @@ class RegistroP990(Registro): CampoFixo(1, 'REG', 'P990'), CampoNumerico(2, 'QTD_LIN_P', obrigatorio=True), ] - + + nivel = 1 class Registro1001(Registro): """ @@ -2847,7 +3045,8 @@ class Registro1001(Registro): CampoFixo(1, 'REG', '1001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + + nivel = 1 class Registro1010(Registro): """ @@ -2862,7 +3061,43 @@ class Registro1010(Registro): Campo(6, 'DESC_DEC_JUD'), CampoData(7, 'DT_SENT_JUD'), ] + + nivel = 2 +class Registro1011(Registro): + """ + Apuração de Crédito Extemporâneo - Documentos e Operações de Períodos Anteriores – PIS/PASEP + """ + campos = [ + CampoFixo(1, 'REG', '1011'), + Campo(2, 'REG_REF'), + CampoChaveEletronica(3, 'CHAVE_DOC'), + Campo(4, 'COD_PART'), + Campo(5, 'COD_ITEM'), + CampoData(6, 'DT_OPER', obrigatorio=True), + CampoNumerico(7, 'VL_OPER', obrigatorio=True), + CampoNumerico(8, 'CST_PIS', obrigatorio=True), + CampoNumerico(9, 'VL_BC_PIS'), + CampoNumerico(10, 'ALIQ_PIS'), + CampoNumerico(11, 'VL_PIS'), + CampoNumerico(12, 'CST_COFINS', obrigatorio=True), + CampoNumerico(13, 'VL_BC_COFINS'), + CampoNumerico(14, 'ALIQ_COFINS'), + CampoNumerico(15, 'VL_COFINS'), + CampoNumerico(16, 'CST_PIS_SUSP', obrigatorio=True), + CampoNumerico(17, 'VL_BC_PIS_SUSP'), + CampoNumerico(18, 'ALIQ_PIS_SUSP'), + CampoNumerico(19, 'VL_PIS_SUSP'), + CampoNumerico(20, 'CST_COFINS_SUSP', obrigatorio=True), + CampoNumerico(21, 'VL_BC_COFINS_SUSP'), + CampoNumerico(22, 'ALIQ_COFINS_SUSP'), + CampoNumerico(23, 'VL_COFINS_SUSP'), + Campo(24, 'COD_CTA'), + Campo(25, 'COD_CCUS'), + Campo(26, 'DESC_DOC_OPER'), + ] + + nivel = 3 class Registro1020(Registro): """ @@ -2874,7 +3109,36 @@ class Registro1020(Registro): Campo(3, 'IND_NAT_ACAO', obrigatorio=True), CampoData(4, 'DT_DEC_ADM', obrigatorio=True), ] - + + nivel = 2 + +class Registro1050(Registro): + """ + Detalhamento de Ajustes de Base de Cálculo – Valores Extra Apuração + """ + campos = [ + CampoFixo(1, 'REG', '1050'), + CampoData(2, 'DT_REF'), + Campo(3, 'IND_AJ_BC'), + CampoCNPJ(4, 'CNPJ'), + CampoNumerico(5, 'VL_AJ_TOT'), + CampoNumerico(6, 'VL_AJ_CST01'), + CampoNumerico(7, 'VL_AJ_CST02'), + CampoNumerico(8, 'VL_AJ_CST03'), + CampoNumerico(9, 'VL_AJ_CST04'), + CampoNumerico(10, 'VL_AJ_CST05'), + CampoNumerico(11, 'VL_AJ_CST06'), + CampoNumerico(12, 'VL_AJ_CST07'), + CampoNumerico(13, 'VL_AJ_CST08'), + CampoNumerico(14, 'VL_AJ_CST09'), + CampoNumerico(15, 'VL_AJ_CST49'), + CampoNumerico(16, 'VL_AJ_CST99'), + Campo(17, 'IND_APROP'), + Campo(18, 'NUM_REC'), + Campo(19, 'INFO_COMPL'), + ] + + nivel = 2 class Registro1100(Registro): """ @@ -2900,7 +3164,8 @@ class Registro1100(Registro): CampoNumerico(17, 'VL_CRED_OUT'), Campo(18, 'SLD_CRED_FIM'), ] - + + nivel = 2 class Registro1101(Registro): """ @@ -2913,14 +3178,14 @@ class Registro1101(Registro): Campo(4, 'COD_MOD'), Campo(5, 'SER'), Campo(6, 'SUB_SER'), - Campo(7, 'NUM_DOC'), + CampoNumerico(7, 'NUM_DOC'), CampoData(8, 'DT_OPER', obrigatorio=True), - Campo(9, 'CHV_NFE'), + CampoChaveEletronica(9, 'CHV_NFE'), CampoNumerico(10, 'VL_OPER', obrigatorio=True), - Campo(11, 'CFOP'), + CampoNumerico(11, 'CFOP'), Campo(12, 'NAT_BC_CRED', obrigatorio=True), Campo(13, 'IND_ORIG_CRED', obrigatorio=True), - Campo(14, 'CST_PIS', obrigatorio=True), + CampoNumerico(14, 'CST_PIS', obrigatorio=True), CampoNumerico(15, 'VL_BC_PIS', obrigatorio=True), CampoNumerico(16, 'ALIQ_PIS', obrigatorio=True), CampoNumerico(17, 'VL_PIS', obrigatorio=True), @@ -2930,7 +3195,8 @@ class Registro1101(Registro): Campo(21, 'PER_ESCRIT'), CampoCNPJ(22, 'CNPJ', obrigatorio=True), ] - + + nivel = 3 class Registro1102(Registro): """ @@ -2942,7 +3208,8 @@ class Registro1102(Registro): CampoNumerico(3, 'VL_CRED_PIS_NT_MI'), CampoNumerico(4, 'VL_CRED_PIS_EXP'), ] - + + nivel = 4 class Registro1200(Registro): """ @@ -2961,7 +3228,8 @@ class Registro1200(Registro): CampoNumerico(10, 'VL_JUR'), CampoData(11, 'DT_RECOL'), ] - + + nivel = 2 class Registro1210(Registro): """ @@ -2970,7 +3238,7 @@ class Registro1210(Registro): campos = [ CampoFixo(1, 'REG', '1210'), CampoCNPJ(2, 'CNPJ', obrigatorio=True), - Campo(3, 'CST_PIS', obrigatorio=True), + CampoNumerico(3, 'CST_PIS', obrigatorio=True), Campo(4, 'COD_PART'), CampoData(5, 'DT_OPER', obrigatorio=True), CampoNumerico(6, 'VL_OPER', obrigatorio=True), @@ -2980,7 +3248,8 @@ class Registro1210(Registro): Campo(10, 'COD_CTA'), Campo(11, 'DESC_COMPL'), ] - + + nivel = 3 class Registro1220(Registro): """ @@ -2993,7 +3262,8 @@ class Registro1220(Registro): Campo(4, 'COD_CRED', obrigatorio=True), CampoNumerico(5, 'VL_CRED', obrigatorio=True), ] - + + nivel = 3 class Registro1300(Registro): """ @@ -3009,7 +3279,8 @@ class Registro1300(Registro): CampoNumerico(7, 'VL_RET_DCOMP', obrigatorio=True), Campo(8, 'SLD_RET', obrigatorio=True), ] - + + nivel = 2 class Registro1500(Registro): """ @@ -3035,7 +3306,8 @@ class Registro1500(Registro): CampoNumerico(17, 'VL_CRED_OUT'), Campo(18, 'SLD_CRED_FIM', obrigatorio=True), ] - + + nivel = 2 class Registro1501(Registro): """ @@ -3048,14 +3320,14 @@ class Registro1501(Registro): Campo(4, 'COD_MOD'), Campo(5, 'SER'), Campo(6, 'SUB_SER'), - Campo(7, 'NUM_DOC'), + CampoNumerico(7, 'NUM_DOC'), CampoData(8, 'DT_OPER', obrigatorio=True), - Campo(9, 'CHV_NFE'), + CampoChaveEletronica(9, 'CHV_NFE'), CampoNumerico(10, 'VL_OPER', obrigatorio=True), - Campo(11, 'CFOP'), + CampoNumerico(11, 'CFOP'), Campo(12, 'NAT_BC_CRED', obrigatorio=True), Campo(13, 'IND_ORIG_CRED', obrigatorio=True), - Campo(14, 'CST_COFINS', obrigatorio=True), + CampoNumerico(14, 'CST_COFINS', obrigatorio=True), CampoNumerico(15, 'VL_BC_COFINS', obrigatorio=True), CampoNumerico(16, 'ALIQ_COFINS', obrigatorio=True), CampoNumerico(17, 'VL_COFINS', obrigatorio=True), @@ -3065,7 +3337,8 @@ class Registro1501(Registro): Campo(21, 'PER_ESCRIT'), CampoCNPJ(22, 'CNPJ', obrigatorio=True), ] - + + nivel = 3 class Registro1502(Registro): """ @@ -3077,7 +3350,8 @@ class Registro1502(Registro): CampoNumerico(3, 'VL_CRED_COFINS_NT_MI'), CampoNumerico(4, 'VL_CRED_COFINS_EXP'), ] - + + nivel = 4 class Registro1600(Registro): """ @@ -3096,7 +3370,8 @@ class Registro1600(Registro): CampoNumerico(10, 'VL_JUR'), CampoData(11, 'DT_RECOL'), ] - + + nivel = 2 class Registro1610(Registro): """ @@ -3105,7 +3380,7 @@ class Registro1610(Registro): campos = [ CampoFixo(1, 'REG', '1610'), CampoCNPJ(2, 'CNPJ', obrigatorio=True), - Campo(3, 'CST_COFINS', obrigatorio=True), + CampoNumerico(3, 'CST_COFINS', obrigatorio=True), Campo(4, 'COD_PART'), CampoData(5, 'DT_OPER', obrigatorio=True), CampoNumerico(6, 'VL_OPER', obrigatorio=True), @@ -3115,7 +3390,8 @@ class Registro1610(Registro): Campo(10, 'COD_CTA'), Campo(11, 'DESC_COMPL'), ] - + + nivel = 3 class Registro1620(Registro): """ @@ -3128,7 +3404,8 @@ class Registro1620(Registro): Campo(4, 'COD_CRED', obrigatorio=True), CampoNumerico(5, 'VL_CRED', obrigatorio=True), ] - + + nivel = 3 class Registro1700(Registro): """ @@ -3144,7 +3421,8 @@ class Registro1700(Registro): CampoNumerico(7, 'VL_RET_DCOMP', obrigatorio=True), Campo(8, 'SLD_RET', obrigatorio=True), ] - + + nivel = 2 class Registro1800(Registro): """ @@ -3161,7 +3439,8 @@ class Registro1800(Registro): CampoData(8, 'DT_REC_UNI'), Campo(9, 'COD_REC'), ] - + + nivel = 2 class Registro1809(Registro): """ @@ -3172,7 +3451,8 @@ class Registro1809(Registro): Campo(2, 'NUM_PROC', obrigatorio=True), Campo(3, 'IND_PROC', obrigatorio=True), ] - + + nivel = 3 class Registro1900(Registro): """ @@ -3185,16 +3465,17 @@ class Registro1900(Registro): Campo(3, 'COD_MOD', obrigatorio=True), Campo(4, 'SER'), Campo(5, 'SUB_SER'), - Campo(6, 'COD_SIT'), + CampoNumerico(6, 'COD_SIT'), CampoNumerico(7, 'VL_TOT_REC', obrigatorio=True), Campo(8, 'QUANT_DOC'), - Campo(9, 'CST_PIS'), - Campo(10, 'CST_COFINS'), - Campo(11, 'CFOP'), + CampoNumerico(9, 'CST_PIS'), + CampoNumerico(10, 'CST_COFINS'), + CampoNumerico(11, 'CFOP'), Campo(12, 'INF_COMPL'), Campo(13, 'COD_CTA'), ] - + + nivel = 2 class Registro1990(Registro): """ @@ -3204,7 +3485,8 @@ class Registro1990(Registro): CampoFixo(1, 'REG', '1990'), CampoNumerico(2, 'QTD_LIN_1', obrigatorio=True), ] - + + nivel = 1 class Registro9001(Registro): """ @@ -3214,7 +3496,8 @@ class Registro9001(Registro): CampoFixo(1, 'REG', '9001'), Campo(2, 'IND_MOV', obrigatorio=True), ] - + + nivel = 1 class Registro9900(Registro): """ @@ -3225,7 +3508,8 @@ class Registro9900(Registro): Campo(2, 'REG_BLC', obrigatorio=True), CampoNumerico(3, 'QTD_REG_BLC', obrigatorio=True), ] - + + nivel = 2 class Registro9990(Registro): """ @@ -3235,7 +3519,8 @@ class Registro9990(Registro): CampoFixo(1, 'REG', '9990'), CampoNumerico(2, 'QTD_LIN_9', obrigatorio=True), ] - + + nivel = 1 class Registro9999(Registro): """ @@ -3245,3 +3530,5 @@ class Registro9999(Registro): CampoFixo(1, 'REG', '9999'), CampoNumerico(2, 'QTD_LIN', obrigatorio=True), ] + nivel = 0 + From ad34f55b67fea5615aaa0b4d6453e7a25e87a498 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:03:05 -0300 Subject: [PATCH 12/52] =?UTF-8?q?[new]=20novo=20diret=C3=B3rio=20e=20arqui?= =?UTF-8?q?vos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 sped/relatorios/__init__.py diff --git a/sped/relatorios/__init__.py b/sped/relatorios/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/sped/relatorios/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- From 46a4a3bf5bfc38d379ccc0edca32256fa451fac5 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:04:43 -0300 Subject: [PATCH 13/52] [new] classes My_Switch e SPED_EFD_Info: imprimir info de arquivos SPED EFD --- sped/relatorios/efd_info.py | 825 ++++++++++++++++++++++++++++++++++++ 1 file changed, 825 insertions(+) create mode 100644 sped/relatorios/efd_info.py diff --git a/sped/relatorios/efd_info.py b/sped/relatorios/efd_info.py new file mode 100644 index 0000000..50235b1 --- /dev/null +++ b/sped/relatorios/efd_info.py @@ -0,0 +1,825 @@ +# -*- coding: utf-8 -*- + +Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' +Data = '28 de Fevereiro de 2020 (início: 10 de Janeiro de 2020)' + +import os, re, sys, itertools, csv +import xlsxwriter # pip install xlsxwriter +from datetime import datetime +from time import time, sleep +from sped.efd.pis_cofins.arquivos import ArquivoDigital as ArquivoDigital_PIS_COFINS +from sped.efd.icms_ipi.arquivos import ArquivoDigital as ArquivoDigital_ICMS_IPI +from sped.relatorios.efd_tabelas import EFD_Tabelas +from sped.campos import CampoData, CampoCNPJ, CampoCPF, CampoCPFouCNPJ, CampoChaveEletronica, CampoNCM + +# Versão mínima exigida: python 3.6.0 +python_version = sys.version_info +if python_version < (3,6,0): + print('versão mínima exigida do python é 3.6.0') + print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) + exit() + +class My_Switch: + """ + Definir, apenas uma vez, um dicionário ao invés de utilizar vários 'if/then/else' a cada + execução de formatar_valor(): + dict[key] = funtion_key(value) + Ao escolher uma chave, o dicionário aplica uma função (que depende da chave) sobre o valor + Esta construção possui Ordem O(1). + Caso fossem utilizados vários if/then/else (ou switch) a ordem seria O(N), que é mais lento! + """ + + @staticmethod + def funcao_identidade(chave): + return chave + + @staticmethod + def formatar_linhas(numero): + return f'{int(numero):09d}' + + @staticmethod + def formatar_mes(mes_num): + try: + mes_num = f'{int(mes_num):02d}' + return f'{EFD_Tabelas.tabela_mes_nominal[mes_num]}' + except: + return mes_num + + @staticmethod + def formatar_registro(registro): + try: + return f'{registro} - {EFD_Tabelas.tabela_info_do_registro[registro]}' + except: + reg = registro[0] + return f'{registro} - {EFD_Tabelas.tabela_info_do_registro[reg]}' + + @staticmethod + def formatar_cfop(cfop): + try: + cfop = f'{int(cfop):04d}' + return f'{cfop} - {EFD_Tabelas.tabela_cfop_descricao[cfop]}' + except: + return cfop + + @staticmethod + def formatar_cst_contrib(codigo_cst): + try: + codigo_cst = f'{int(codigo_cst):02d}' + return f'{codigo_cst} - {EFD_Tabelas.tabela_cst_contrib[codigo_cst]}' + except: + return codigo_cst + + @staticmethod + def formatar_cst_icms(codigo_cst): + try: + codigo_cst = f'{int(codigo_cst):03d}' + return f'{codigo_cst} - {EFD_Tabelas.tabela_cst_icms[codigo_cst]}' + except: + return codigo_cst + + @staticmethod + def formatar_nbc(natureza_bc): + try: + natureza_bc = f'{int(natureza_bc):02d}' + return f'{natureza_bc} - {EFD_Tabelas.tabela_bc_do_credito[natureza_bc]}' + except: + return natureza_bc + + @staticmethod + def formatar_tipo(tipo_do_item): + try: + tipo_do_item = f'{int(tipo_do_item):02d}' + return f'{tipo_do_item} - {EFD_Tabelas.tabela_tipo_do_item[tipo_do_item]}' + except: + return tipo_do_item + + @staticmethod + def formatar_mod(doc_fiscal): + try: + return f'{doc_fiscal} - {EFD_Tabelas.tabela_modelos_documentos_fiscais[doc_fiscal]}' + except: + return doc_fiscal + + @staticmethod + def formatar_valores_reais(valor): + try: + return float(valor) + except: + valor = valor.replace( '.', '' ) # 4.218.239,19 --> 4218239,19 + valor = valor.replace( ',', '.' ) # 4218239,19 --> 4218239.19 + return float(valor) + + @staticmethod + def formatar_datas(data): + date_time = datetime.strptime(data, "%d/%m/%Y") # dd/mm/aaaa + return date_time + + # initialize the attributes of the class + + def __init__(self, lista_de_colunas, verbose=False): + + self.lista_de_colunas = lista_de_colunas + + self.verbose = verbose + + self.dicionario = {} + + def formatar_colunas_do_arquivo_csv(self): + + for nome_da_coluna in self.lista_de_colunas: + + match_linha = re.search(r'^Linhas', nome_da_coluna, flags=re.IGNORECASE) + match_mes = re.search(r'^Mês do Período', nome_da_coluna, flags=re.IGNORECASE) + match_reg = re.search(r'^REG', nome_da_coluna, flags=re.IGNORECASE) + match_cfop = re.search(r'^CFOP', nome_da_coluna, flags=re.IGNORECASE) + match_nbc = re.search(r'NAT_BC_CRED', nome_da_coluna, flags=re.IGNORECASE) + match_tipo = re.search(r'TIPO_ITEM', nome_da_coluna, flags=re.IGNORECASE) + match_mod = re.search(r'COD_MOD', nome_da_coluna, flags=re.IGNORECASE) + match_data = re.search(r'^DT_|Data', nome_da_coluna, flags=re.IGNORECASE) + match_chave = re.search(r'^CHV_|Chave Eletrônica', nome_da_coluna, flags=re.IGNORECASE) + match_ncm = re.search(r'COD_NCM', nome_da_coluna, flags=re.IGNORECASE) + match_cnpj = re.search(r'CNPJ', nome_da_coluna, flags=re.IGNORECASE) + match_cpf = re.search(r'CPF', nome_da_coluna, flags=re.IGNORECASE) + + match_cst_contib = re.search(r'^CST_(PIS|COFINS)|CST_PIS_COFINS', nome_da_coluna, flags=re.IGNORECASE) + match_cst_icms = re.search(r'^CST_ICMS', nome_da_coluna, flags=re.IGNORECASE) + + # https://www.geeksforgeeks.org/switch-case-in-python-replacement/ + # Ao invés de usar vários 'if/elif/elif/elif/.../else', usar o dict switcher[chave] = valor, + # tal que switcher.get(True, 'default value') retorna o valor da última chave True. + # bool(match_linha) retorna True ou False. + switcher = { + bool(match_linha): self.formatar_linhas, + bool(match_mes): self.formatar_mes, + bool(match_reg): self.formatar_registro, + bool(match_cfop): self.formatar_cfop, + bool(match_nbc): self.formatar_nbc, + bool(match_tipo): self.formatar_tipo, + bool(match_mod): self.formatar_mod, + bool(match_cst_contib): self.formatar_cst_contrib, + bool(match_cst_icms): self.formatar_cst_icms, + bool(match_data): CampoData.formatar, + bool(match_chave): CampoChaveEletronica.formatar, + bool(match_ncm): CampoNCM.formatar, + bool(match_cnpj): CampoCNPJ.formatar, + bool(match_cpf): CampoCPF.formatar, + bool(match_cnpj and match_cpf): CampoCPFouCNPJ.formatar, + } + + # Caso não ocorra nenhum match, retornar default value = self.funcao_identidade + self.dicionario[nome_da_coluna] = switcher.get(True, self.funcao_identidade) + + #print(f'{switcher = } ; {nome_da_coluna = } ; {bool(match_data) = } ; {self.dicionario[nome_da_coluna] = } \n') + #sleep(0.5) + + if self.verbose: + for idx, key in enumerate(sorted(self.dicionario.keys()),1): + print(f'{key:>40}: [{idx:>2}] {self.dicionario[key]}') + + def formatar_valores_das_colunas(self): + + for nome_da_coluna in self.lista_de_colunas: + + match_n_center = re.search(r'Linha|NUM_ITEM', nome_da_coluna, flags=re.IGNORECASE) + match_n_right = re.search(r'NUM_DOC', nome_da_coluna, flags=re.IGNORECASE) + match_valor = re.search(r'VL|Valor', nome_da_coluna, flags=re.IGNORECASE) + match_aliquota = re.search(r'Aliq', nome_da_coluna, flags=re.IGNORECASE) + match_data = re.search(r'Data|DT_', nome_da_coluna, flags=re.IGNORECASE) + + self.dicionario[nome_da_coluna] = self.funcao_identidade + + # Estes vários if/elif/elif/... são executados apenas uma vez na execução do método/função. + if match_n_center or match_n_right or match_valor or match_aliquota: + self.dicionario[nome_da_coluna] = self.formatar_valores_reais + elif match_data: + self.dicionario[nome_da_coluna] = self.formatar_datas + + def formatar_colunas_do_arquivo_excel(self,workbook): + + format_default = workbook.add_format() + format_n_center = workbook.add_format({'num_format': '0', 'align':'center'}) + format_n_right = workbook.add_format({'num_format': '0', 'align':'right'}) + format_valor = workbook.add_format({'num_format': '#,##0.00', 'align':'right'}) + format_aliquota = workbook.add_format({'num_format': '#,##0.0000', 'align':'center'}) + format_data = workbook.add_format({'num_format': 'dd/mm/yyyy', 'align':'center'}) + format_center = workbook.add_format({'align':'center'}) + + for nome_da_coluna in self.lista_de_colunas: + + match_n_center = re.search(r'Linha|NUM_ITEM', nome_da_coluna, flags=re.IGNORECASE) + match_n_right = re.search(r'NUM_DOC', nome_da_coluna, flags=re.IGNORECASE) + match_valor = re.search(r'VL|Valor', nome_da_coluna, flags=re.IGNORECASE) + match_aliquota = re.search(r'Aliq', nome_da_coluna, flags=re.IGNORECASE) + match_data = re.search(r'Data|DT_', nome_da_coluna, flags=re.IGNORECASE) + match_center = re.search(r'Período|Operação', nome_da_coluna, flags=re.IGNORECASE) + + switcher = { + bool(match_n_center): format_n_center, + bool(match_n_right): format_n_right, + bool(match_valor): format_valor, + bool(match_aliquota): format_aliquota, + bool(match_data): format_data, + bool(match_center): format_center, + } + + # Caso não ocorra nenhum match, retornar default value = format_default + self.dicionario[nome_da_coluna] = switcher.get(True, format_default) + + +# Python OOP: Atributos e Métodos (def, funções) +class SPED_EFD_Info: + """ + Imprimir SPED EFD Contribuições ou ICMS_IPI nos formatos .csv e .xlsx tal que + contenha todas as informações suficientes para verificar a correção dos lançamentos + ou apuração das contribuições de PIS/COFINS ou do ICMS segundo a legislação vigente. + """ + + # class or static variable + + # Python 3 Deep Dive (Part 4 - OOP)/03. Project 1/03. Project Solution - Transaction Numbers + contador_de_linhas = itertools.count(2) # 2 é o valor inicial do contador + + ### --- registros e colunas --- ### + + # 'Data da Emissão do Documento Fiscal' + registros_de_data_emissao = ['DT_DOC', 'DT_DOC_INI', 'DT_REF_INI', 'DT_OPER'] + + # 'Data da Entrada/Aquisição/Execução ou da Saída/Prestação/Conclusão' + registros_de_data_execucao = ['DT_EXE_SERV', 'DT_E_S', 'DT_ENT', 'DT_A_P', 'DT_DOC_FIN', 'DT_REF_FIN'] + + # merge/concatenating two lists in Python + registros_de_data = ['DT_INI', 'DT_FIN'] + registros_de_data_emissao + registros_de_data_execucao + + registros_de_identificacao_do_item = ['DESCR_ITEM', 'TIPO_ITEM', 'COD_NCM'] + + registros_de_cadastro_do_participante = ['NOME_participante', 'CNPJ_participante', 'CPF_participante'] + + registros_de_plano_de_contas = ['COD_NAT_CC', 'NOME_CTA'] + + registros_de_codigo_cst = ['CST_PIS', 'CST_COFINS'] + + registros_de_chave_eletronica = ['CHV_NFE', 'CHV_CTE', 'CHV_NFSE', 'CHV_DOCe', 'CHV_CFE', 'CHV_NFE_CTE'] + + # adicionado 'VL_OPR' para EFD ICMS_IPI + registros_de_valor = ['VL_DOC', 'VL_BRT', 'VL_OPER', 'VL_OPR', 'VL_OPER_DEP', 'VL_BC_CRED', 'VL_BC_EST', + 'VL_TOT_REC', 'VL_REC_CAIXA', 'VL_REC_COMP', 'VL_REC', 'VL_ITEM'] + + # Imprimir as informações desta coluna, nesta ordem + colunas_selecionadas = [ + 'Linhas', 'Arquivo da SPED EFD', 'Nº da Linha da EFD', 'CNPJ', 'NOME', 'Mês do Período de Apuração', + 'Ano do Período de Apuração', 'Tipo de Operação', 'IND_ORIG_CRED', 'REG', 'CST_PIS_COFINS', + 'NAT_BC_CRED', 'CFOP', 'COD_PART', *registros_de_cadastro_do_participante, 'CNPJ_CPF_PART', + 'Data de Emissão', 'Data de Execução', 'COD_ITEM', *registros_de_identificacao_do_item, + 'Chave Eletrônica', 'COD_MOD', 'NUM_DOC', 'NUM_ITEM', 'COD_CTA', *registros_de_plano_de_contas, + 'Valor do Item', 'VL_BC_PIS', 'VL_BC_COFINS', 'ALIQ_PIS', 'ALIQ_COFINS', + 'VL_ISS', 'CST_ICMS', 'VL_BC_ICMS', 'ALIQ_ICMS' + ] + + # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? + registros_totais = set( + registros_de_data + registros_de_identificacao_do_item + registros_de_plano_de_contas + + registros_de_codigo_cst + registros_de_chave_eletronica + registros_de_valor + + colunas_selecionadas) + + # initialize the attributes of the class + + def __init__(self, file_path=None, encoding=None, efd_tipo=None, verbose=False): + + if file_path is None or not os.path.isfile(file_path): + raise ValueError(f'O arquivo file_path = {file_path} não é válido!') + else: + self.file_path = file_path + + if encoding is None: + self.encoding = 'UTF-8' + else: + self.encoding = encoding + + if efd_tipo is None or re.search(r'PIS|COFINS|Contrib', efd_tipo, flags=re.IGNORECASE): + self.objeto_sped = ArquivoDigital_PIS_COFINS() # instanciar objeto sped_efd + self.efd_tipo = 'efd_contribuicoes' + elif re.search(r'ICMS|IPI', efd_tipo, flags=re.IGNORECASE): + self.objeto_sped = ArquivoDigital_ICMS_IPI() # instanciar objeto sped_efd + self.efd_tipo = 'efd_icms_ipi' + else: + raise ValueError(f'efd_tipo = {efd_tipo} inválido!') + + if not isinstance(verbose, bool): + raise ValueError(f'verbose deve ser uma variável boolean (True or False). verbose = {verbose} é inválido!') + else: + self.verbose = verbose + + self.basename = os.path.basename(self.file_path) + + self.myDict = {} + + @property + def imprimir_informacoes(self): + + select_object = My_Switch(type(self).registros_totais,verbose=self.verbose) + select_object.formatar_colunas_do_arquivo_csv() + self.myDict = select_object.dicionario + + self.objeto_sped.readfile(self.file_path, codificacao=self.encoding, verbose=self.verbose) + + self.info_do_participante = self.cadastro_do_participante(self.objeto_sped) + + if self.verbose: + print(f'self.info_do_participante = {self.info_do_participante} ; len(self.info_do_participante) = {len(self.info_do_participante)}\n') + + self.info_do_item = self.identificacao_do_item(self.objeto_sped) + + if self.verbose: + print(f'self.info_do_item = {self.info_do_item} ; len(self.info_do_item) = {len(self.info_do_item)}\n') + + self.info_da_conta = self.plano_de_contas_contabeis(self.objeto_sped) + + if self.verbose: + print(f'self.info_da_conta = {self.info_da_conta} ; len(self.info_da_conta) = {len(self.info_da_conta)}\n') + + self.info_de_abertura = self.obter_info_de_abertura(self.objeto_sped) + + filename, _ = os.path.splitext(self.file_path) + arquivo_csv = filename + '.csv' + arquivo_excel = filename + '.xlsx' + + self.imprimir_informacoes_da_efd(self.objeto_sped, output_filename=arquivo_csv) + + self.convert_csv_to_xlsx(imput_csv=arquivo_csv, output_excel=arquivo_excel) + + def __repr__(self): + # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance + # Devo substituir 'self.__class__.static_var' por 'type(self).static_var' ? + return f'{type(self).__name__}(file_path={self.file_path!r}, encoding={self.encoding!r}, efd_tipo={self.efd_tipo!r}, verbose={self.verbose!r})' + + def formatar_valor(self,nome,val): + """ + Evitar n repetições de 'if condicao_j then A_j else B_j' tal que 1 <= j <= n, + usar dicionário: myDict[key] = funtion_key(value) + Better optimization technique using if/else or dictionary + A series of if/else statement which receives the 'string' returns the appropriate function for it. + A dictionary maintaining the key-value pair. key as strings, and values as the function objects, + and one main function to search and return the function object. + """ + # https://stackoverflow.com/questions/11445226/better-optimization-technique-using-if-else-or-dictionary + # https://softwareengineering.stackexchange.com/questions/182093/why-store-a-function-inside-a-python-dictionary/182095 + # https://stackoverflow.com/questions/9168340/using-a-dictionary-to-select-function-to-execute + try: + # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance + # val_formated = self.__class__.myDict[nome](val) + val_formated = self.myDict[nome](val) + except: + val_formated = val + #print(f'nome = {nome} ; val = {val} ; val_formated = {val_formated}') + return val_formated + + # https://radek.io/2011/07/21/static-variables-and-methods-in-python/ + @staticmethod + def natureza_da_bc_dos_creditos(cfop): + """ + http://sped.rfb.gov.br/arquivo/show/1681 + Tabela CFOP - Operações Geradoras de Créditos - Versão 1.0.0 + """ + natureza_bc = None + + # Código 01 - CFOP de 'Aquisição de Bens para Revenda' + if cfop in ['1102','1113','1117','1118','1121','1251','1403','1652','2102','2113', + '2117','2118','2121','2251','2403','2652','3102','3251','3652']: + natureza_bc = 1 + # Código 02 - CFOP de 'Aquisição de Bens Utilizados como Insumo' + elif cfop in ['1101','1111','1116','1120','1122','1126','1128','1401','1407','1556', + '1651','1653','2101','2111','2116','2120','2122','2126','2128','2401', + '2407','2556','2651','2653','3101','3126','3128','3556','3651','3653']: + natureza_bc = 2 + # Código 03 - CFOP de 'Aquisição de Serviços Utilizados como Insumos' + elif cfop in ['1124','1125','1933','2124','2125','2933']: + natureza_bc = 3 + # Código 12 - CFOP de 'Devolução de Vendas Sujeitas à Incidência Não-Cumulativa' + elif cfop in ['1201','1202','1203','1204','1410','1411','1660','1661','1662','2201', + '2202','2410','2411','2660','2661','2662']: + natureza_bc = 12 + # Código 13 - CFOP de 'Outras Operações com Direito a Crédito' + elif cfop in ['1922','2922']: + natureza_bc = 13 + + return natureza_bc + + # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance + def cadastro_do_participante(self,sped_efd): + """ + Registro 0150: Tabela de Cadastro do Participante + Retorno desta função: + info_do_participante[codigo_do_participante][campo] = descricao + """ + blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. + info = {} + for registro in blocoZero.registros: + REG = registro.valores[1] + if REG != '0150': + continue + codigo_do_participante = None + for campo in registro.campos: + valor = registro.valores[campo.indice] + # Fazer distinção entre 'NOME' do Registro0000 e 'NOME' do Registro0150 + nome = campo.nome + '_participante' + if campo.nome == 'COD_PART': + codigo_do_participante = valor + info[codigo_do_participante] = {} + if nome in type(self).registros_de_cadastro_do_participante and codigo_do_participante is not None: + info[codigo_do_participante][nome] = valor + return info + + def identificacao_do_item(self,sped_efd): + """ + Registro 0200: Tabela de Identificação do Item (Produtos e Serviços) + Retorno desta função: + info_do_item[codigo_do_item][campo] = descricao + """ + blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. + info = {} + for registro in blocoZero.registros: + REG = registro.valores[1] + if REG != '0200': + continue + codigo_do_item = None + for campo in registro.campos: + valor = registro.valores[campo.indice] + if campo.nome == 'COD_ITEM': + codigo_do_item = valor + info[codigo_do_item] = {} + if campo.nome in type(self).registros_de_identificacao_do_item and codigo_do_item is not None: + info[codigo_do_item][campo.nome] = valor + return info + + def plano_de_contas_contabeis(self,sped_efd): + """ + Registro 0500: Plano de Contas Contábeis + Retorno desta função: + info_do_item[codigo_do_item][campo] = descricao + """ + blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. + info = {} + for registro in blocoZero.registros: + REG = registro.valores[1] + if REG != '0500': + continue + codigo_do_item = None + for campo in registro.campos: + valor = registro.valores[campo.indice] + if campo.nome == 'COD_CTA': + codigo_do_item = valor + info[codigo_do_item] = {} + for campo in registro.campos: + valor = registro.valores[campo.indice] + if campo.nome in type(self).registros_de_plano_de_contas and codigo_do_item is not None: + info[codigo_do_item][campo.nome] = valor + return info + + + def obter_info_de_abertura(self,sped_efd): + registro = sped_efd._registro_abertura + REG = registro.valores[1] + nivel = registro.nivel + + # Utilizar uma combinação de valores para identificar univocamente um item. + combinacao = 'registro de abertura' + + info_de_abertura = {} + + # https://www.geeksforgeeks.org/python-creating-multidimensional-dictionary/ + info_de_abertura.setdefault(nivel, {}).setdefault(combinacao, {})['Nível Hierárquico'] = nivel + + if self.verbose: + print(f'registro.as_line() = {registro.as_line()} ; REG = {REG} ; nivel = {nivel}') + print(f'info_de_abertura = {info_de_abertura}\n') + + for campo in registro.campos: + + valor = registro.valores[campo.indice] + + if campo.nome in type(self).colunas_selecionadas: + info_de_abertura[nivel][combinacao][campo.nome] = valor + if campo.nome == 'DT_INI': + ddmmaaaa = registro.valores[campo.indice] + info_de_abertura[nivel][combinacao]['Data de Emissão'] = valor + info_de_abertura[nivel][combinacao]['Mês do Período de Apuração'] = ddmmaaaa[2:4] + info_de_abertura[nivel][combinacao]['Ano do Período de Apuração'] = ddmmaaaa[4:8] + if campo.nome == 'DT_FIN': + info_de_abertura[nivel][combinacao]['Data de Execução'] = valor + if self.verbose: + valor_formatado = self.formatar_valor(nome=campo.nome, val=valor) + print(f'campo.indice = {campo.indice:>2} ; campo.nome = {campo.nome:>22} ; registro.valores[{campo.indice:>2}] = {valor:<50} ; valor_formatado = {valor_formatado}') + + if self.verbose: + print(f'\ninfo_de_abertura = {info_de_abertura}\n') + + return info_de_abertura + + def adicionar_informacoes(self,dict_info): + """ + Adicionar informações em dict_info + Formatar alguns de seus campos com o uso de tabelas ou funções + """ + dict_info['Arquivo da SPED EFD'] = self.basename + dict_info['Linhas'] = next(type(self).contador_de_linhas) + + # re.search: find something anywhere in the string and return a match object. + if 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS']): + cst = int(dict_info['CST_PIS_COFINS']) + if 1 <= cst <= 49: + dict_info['Tipo de Operação'] = 'Saída' + elif 50 <= cst <= 99: + dict_info['Tipo de Operação'] = 'Entrada' + + # adicionar informação de NAT_BC_CRED para os créditos (50 <= cst <= 66) + # quando houver informação do CFOP e NAT_BC_CRED estiver vazio. + if ('CFOP' in dict_info and 'NAT_BC_CRED' in dict_info + and re.search(r'\d{4}', dict_info['CFOP']) and len(dict_info['NAT_BC_CRED']) == 0 + #and ( re.search(r'[1-9]', dict_info['ALIQ_PIS']) or re.search(r'[1-9]', dict_info['ALIQ_COFINS']) ) # aliq_cofins > 0 + and 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS'])): + cfop = str(dict_info['CFOP']) + cst = int(dict_info['CST_PIS_COFINS']) + if 50 <= cst <= 66: + dict_info['NAT_BC_CRED'] = type(self).natureza_da_bc_dos_creditos(cfop) + + # Índice de Origem do Crédito: Leia os comentários do 'Registro M100: Crédito de PIS/Pasep Relativo ao Período'. + # Os códigos vinculados à importação (108, 208 e 308) são obtidos através da informação de CFOP + # iniciado em 3 (quando existente) ou pelo campo IND_ORIG_CRED nos demais casos. + indicador_de_origem = 'Mercado Interno' # Default Value: 0 - Mercado Interno ; 1 - Mercado Externo (Importação). + if (('CFOP' in dict_info and re.search(r'^3\d{3}', dict_info['CFOP'])) or + ('IND_ORIG_CRED' in dict_info and dict_info['IND_ORIG_CRED'] == '1')): + indicador_de_origem = 'Mercado Externo (Importação)' + dict_info['IND_ORIG_CRED'] = indicador_de_origem + + # adicionar informação de cadastro do participante obtido do Registro 0150 + # info_do_participante[codigo_do_participante][campo] = descricao + if 'COD_PART' in dict_info and dict_info['COD_PART'] in self.info_do_participante: + codigo_do_participante = dict_info['COD_PART'] + for campo in self.info_do_participante[codigo_do_participante]: + dict_info[campo] = self.info_do_participante[codigo_do_participante][campo] + + # adicionar informação de identificação do item obtido do Registro 0200 + # info_do_item[codigo_do_item][campo] = descricao + if 'COD_ITEM' in dict_info and dict_info['COD_ITEM'] in self.info_do_item: + codigo_do_item = dict_info['COD_ITEM'] + for campo in self.info_do_item[codigo_do_item]: + dict_info[campo] = self.info_do_item[codigo_do_item][campo] + + # adicionar informação do plano de contas obtido do Registro 0500 + # info_da_conta[codigo_da_conta][campo] = descricao + if 'COD_CTA' in dict_info and dict_info['COD_CTA'] in self.info_da_conta: + codigo_da_conta = dict_info['COD_CTA'] + for campo in self.info_da_conta[codigo_da_conta]: + val = str(self.info_da_conta[codigo_da_conta][campo]) + if campo == 'COD_NAT_CC' and re.search(r'\d{1,2}', val): + val = val.zfill(2) # val = f'{int(val):02d}' + val = val + ' - ' + EFD_Tabelas.tabela_natureza_da_conta[val] + dict_info[campo] = val + + # Ao final, formatar alguns valores dos campos + for campo in dict_info.copy(): + valor_formatado = self.formatar_valor(nome=campo, val=dict_info[campo]) + dict_info[campo] = valor_formatado + + return dict_info + + def imprimir_informacoes_da_efd(self,sped_efd,output_filename): + + my_regex = r'^[A-K]' # Ler os blocos da A a K. + + campos_necessarios = ['CST_PIS', 'CST_COFINS', 'VL_BC_PIS', 'VL_BC_COFINS'] + # Bastam os seguintes campos, desde que os registros de PIS/PASEP ocorram sempre anteriores aos registros de COFINS: + # campos_necessarios = ['CST_COFINS', 'VL_BC_COFINS'] + + if self.efd_tipo == 'efd_icms_ipi': + campos_necessarios = ['CST_ICMS', 'VL_BC_ICMS'] + + # https://docs.python.org/3/library/csv.html + with open(output_filename, 'w', newline='', encoding='utf-8', errors='ignore') as csvfile: + + writer = csv.writer(csvfile, delimiter=';') + writer.writerow(type(self).colunas_selecionadas) # imprimir nomes das colunas apenas uma vez + + for key in sped_efd._blocos.keys(): + + match_bloco = re.search(my_regex, key, flags=re.IGNORECASE) + if not match_bloco: + continue + + bloco = sped_efd._blocos[key] + count = 1 + + info = self.info_de_abertura + + for registro in bloco.registros: + + REG = registro.valores[1] + + try: + nivel_anterior = nivel + num_de_campos_anterior = num_de_campos + except: + nivel_anterior = registro.nivel + 1 + num_de_campos_anterior = len(registro.campos) + 1 + + nivel = registro.nivel # nível atual + num_de_campos = len(registro.campos) + + cst_pis = '' # 2 caracteres + cst_cofins = '' # 2 caracteres + cst_icms = '' # 3 caracteres + cfop = 'cfop' # 4 caracteres + valor_item = 'valor_item' + + for campo in registro.campos: + if campo.nome == 'CST_PIS': + cst_pis = registro.valores[campo.indice] + if campo.nome == 'CST_COFINS': + cst_cofins = registro.valores[campo.indice] + if campo.nome == 'CST_ICMS': + cst_icms = registro.valores[campo.indice] + if campo.nome == 'CFOP': + cfop = registro.valores[campo.indice] + if campo.nome in type(self).registros_de_valor: + valor_item = registro.valores[campo.indice] + + cst_contribuicao = max(cst_pis,cst_cofins) + + # Utilizar uma combinação de valores para identificar univocamente um item. + combinacao = f'{cst_contribuicao}_{cst_icms}_{cfop}_{valor_item}' + + if self.verbose: + print(f'\ncount = {count:>2} ; key = {key} ; REG = {REG} ; nivel_anterior = {nivel_anterior} ; nivel = {nivel} ; ', end='') + print(f'num_de_campos_anterior = {num_de_campos_anterior} ; num_de_campos = {num_de_campos} ; ', end='') + print(f'cst_pis = {cst_pis} ; cst_cofins = {cst_cofins} ; cst_contribuicao = {cst_contribuicao}') + print(f'registro.as_line() = {registro.as_line()}') + + # As informações do pai e respectivos filhos devem ser apagadas quando + # o nivel hierárquico regride dos filhos para pais diferentes. + if nivel < nivel_anterior or (nivel == nivel_anterior and num_de_campos < num_de_campos_anterior): + if self.verbose: + if nivel < nivel_anterior: + print(f'\n nivel atual: nivel = {nivel} < nivel_anterior = {nivel_anterior} ; ', end='') + if nivel == nivel_anterior and num_de_campos < num_de_campos_anterior: + print(f'\n numero de campos atual: num_de_campos = {num_de_campos} < num_de_campos_anterior = {num_de_campos_anterior} ; ', end='') + print(f'deletar informações em info a partir do nível {nivel} em diante:') + + # Delete items from dictionary while iterating: + # https://www.geeksforgeeks.org/python-delete-items-from-dictionary-while-iterating/ + for nv in list(info): + if nv >= nivel: + del info[nv] + if self.verbose: + print(f'\t *** deletar informações do nível {nv}: del info[{nv}] ***') + print() if self.verbose else 0 + + # https://www.geeksforgeeks.org/python-creating-multidimensional-dictionary/ + info.setdefault(nivel, {}).setdefault(combinacao, {})['Nível Hierárquico'] = nivel + info[nivel][combinacao]['Valor do Item'] = valor_item + info[nivel][combinacao]['CST_PIS_COFINS'] = cst_contribuicao + + for campo in registro.campos: + + try: + valor = registro.valores[campo.indice] + except: + valor = f'{REG}[{campo.indice}:{campo.nome}] sem valor definido' + + if self.verbose: + valor_formatado = self.formatar_valor(nome=campo.nome, val=valor) + print(f'campo.indice = {campo.indice:>2} ; campo.nome = {campo.nome:>22} ; registro.valores[{campo.indice:>2}] = {valor:<50} ; valor_formatado = {valor_formatado}') + + if campo.nome not in type(self).registros_totais: # filtrar registros_totais + continue + + # reter em info{} as informações dos registros contidos em registros_totais + info[nivel][combinacao][campo.nome] = valor + + # Informar os campos em registros_de_data_emissao na coluna 'Data de Emissão'. + if campo.nome in type(self).registros_de_data_emissao: + info[nivel][combinacao]['Data de Emissão'] = valor + # Informar os campos em registros_de_data_execucao na coluna 'Data de Execução'. + if campo.nome in type(self).registros_de_data_execucao: + info[nivel][combinacao]['Data de Execução'] = valor + # Informar os campos de chave eletrônica de 44 dígitos na coluna 'Chave Eletrônica'. + if campo.nome in type(self).registros_de_chave_eletronica: + info[nivel][combinacao]['Chave Eletrônica'] = valor + + if self.verbose: + print(f'\n-->info[nivel][combinacao] = info[{nivel}][{combinacao}] = {info[nivel][combinacao]}\n') + + #https://stackoverflow.com/questions/3931541/how-to-check-if-all-of-the-following-items-are-in-a-list + # set(['a', 'c']).issubset(['a', 'b', 'c', 'd']) or set(lista1).issubset(lista2) + + if set(campos_necessarios).issubset( info[nivel][combinacao] ): + + # import this: Zen of Python: Flat is better than nested. + flattened_info = {} # eliminar os dois niveis [nivel][combinacao] e trazer todas as informações para apenas uma dimensão. + seen_column = set() # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? + + # em info{} há os registros_totais, em flattened_info{} apenas as colunas para impressao + for coluna in type(self).colunas_selecionadas: + flattened_info[coluna] = '' # atribuir valor inicial para todas as colunas + + if coluna in info[nivel][combinacao]: + flattened_info[coluna] = info[nivel][combinacao][coluna] # eliminar os dois niveis [nivel][combinacao] + seen_column.add(coluna) + if self.verbose: + print(f'nivel = {nivel:<10} ; combinacao = {combinacao:25} ; coluna = {coluna:>35} = {info[nivel][combinacao][coluna]:<35} ; info[nivel][combinacao] = {info[nivel][combinacao]}') + continue + + for nv in sorted(info,reverse=True): # nível em ordem decrescente + if coluna in seen_column: # informações já obtidas + break # as informações obtidas do nível mais alto prevalecerá + for comb in info[nv]: + if coluna in info[nv][comb]: + flattened_info[coluna] = info[nv][comb][coluna] # eliminar os dois niveis [nivel][combinacao] + seen_column.add(coluna) + if self.verbose: + print(f'nivel = {nivel} ; nv = {nv} ; combinacao = {comb:25} ; coluna = {coluna:>35} = {info[nv][comb][coluna]:<35} ; info[nivel][combinacao] = {info[nv][comb]}') + + print() if self.verbose else 0 + + flattened_info['Nº da Linha da EFD'] = registro.numero_da_linha + + # Adicionar informações em flattened_info ou formatar alguns de seus campos com o uso de tabelas ou funções + flattened_info = self.adicionar_informacoes(flattened_info) + + writer.writerow( flattened_info.values() ) + + # Se verbose == True, limitar tamanho do arquivo impresso + # Imprimir apenas os 20 primeiros registros de cada Bloco + count += 1 + if self.verbose and count > 20: + break + + print(f"Gerado o arquivo csv: '{output_filename}'.") + + + def convert_csv_to_xlsx(self, imput_csv, output_excel): + + # Create an new Excel file and add a worksheet. + workbook = xlsxwriter.Workbook(output_excel) + worksheet = workbook.add_worksheet('Itens de Docs Fiscais') + workbook.set_properties({'comments': 'Created with Python and XlsxWriter'}) + + # definindo a altura da primeira coluna, row_index == 0 + worksheet.set_row(0, 30) + + # Freeze pane on the top row. + worksheet.freeze_panes(1, 0) + + # Set up some formatting + header_format = workbook.add_format({ + 'align':'center', 'valign':'vcenter', + 'bg_color':'#C5D9F1', 'text_wrap':True, + 'font_size':10}) + + select_value = My_Switch(type(self).registros_totais,verbose=self.verbose) + select_value.formatar_valores_das_colunas() + myValue = select_value.dicionario + + select_format = My_Switch(type(self).registros_totais,verbose=self.verbose) + select_format.formatar_colunas_do_arquivo_excel(workbook) + myFormat = select_format.dicionario + + # First we find the length of the header column + largura_max = [len(c) for c in type(self).colunas_selecionadas] + + with open(imput_csv, 'r', encoding='utf-8', errors='ignore') as file: + + reader = csv.reader(file, delimiter=';') + for row_index, row in enumerate(reader): + + # nomes das colunas + if row_index == 0: + worksheet.write_row(row_index, 0, tuple(type(self).colunas_selecionadas), header_format) + continue + + for column_index, cell in enumerate(row): + + # reter largura máxima + if len(cell) > largura_max[column_index]: + largura_max[column_index] = len(cell) + + column_name = type(self).colunas_selecionadas[column_index] + + if len(cell) > 0: + worksheet.write(row_index, column_index, myValue[column_name](cell), myFormat[column_name]) + else: + # Write cell with row/column notation. + worksheet.write(row_index, column_index, cell) + + # Ajustar largura das colunas com os valores máximos + largura_min = 4 + for i, width in enumerate(largura_max): + if width > 120: # largura máxima + width = 120 + worksheet.set_column(i, i, width + largura_min) + + # Set the autofilter( $first_row, $first_col, $last_row, $last_col ) + worksheet.autofilter(0, 0, 0, len(largura_max) - 1) + + workbook.close() + + print(f"Gerado o arquivo XLSX Excel: '{output_excel}'.") From 8eb6f49c628d2544123f8afd4ee9a6c6f98cf0e1 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:06:26 -0300 Subject: [PATCH 14/52] =?UTF-8?q?[new]=20encontrar=20arquivos=20SPED=20EFD?= =?UTF-8?q?=20no=20diret=C3=B3rio=20indicado?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_read_dir.py | 212 ++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100755 sped/relatorios/efd_read_dir.py diff --git a/sped/relatorios/efd_read_dir.py b/sped/relatorios/efd_read_dir.py new file mode 100755 index 0000000..b7b6079 --- /dev/null +++ b/sped/relatorios/efd_read_dir.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import re, os, glob, sys +import cchardet as chardet # pip3 install cchardet + +Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' +Data = '06 de Fevereiro de 2020 (início: 15 de Dezembro de 2020)' + +# Versão mínima exigida: python 3.6.0 +python_version = sys.version_info +if python_version < (3,6,0): + print('versão mínima exigida do python é 3.6.0') + print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) + exit() + +# Python OOP: Atributos e Métodos (def, funções) +class ReadFiles: + """Retorna um dicionário com informações dos arquivos encontrados no diretório""" + recursive = True + current_dir = os.getcwd() + seen_file = set() # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? + + def __init__(self, root_path = None, extension = None, pattern = None): + if root_path is None: + self.root_path = self.current_dir + else: + self.root_path = root_path + if extension is None: + self.extension = '*' + else: + self.extension = extension.strip('.') + if pattern is None: + self.pattern = '.' + else: + self.pattern = pattern + self.informations = {} # instance attributes, dict + + def __repr__(self): + return f'{self.__class__.__name__}(root_path = {self.root_path!r}, extension = {self.extension!r}, pattern = {self.pattern!r})' + + def get_file_extension(self,file_path): + # https://stackoverflow.com/questions/541390/extracting-extension-from-filename-in-python + _, file_extension = os.path.splitext(file_path) + return file_extension + + def get_filename(self,file_path): + # https://stackoverflow.com/questions/541390/extracting-extension-from-filename-in-python + filename = os.path.basename(file_path) + return filename + + # https://stackoverflow.com/questions/9629179/python-counting-lines-in-a-huge-10gb-file-as-fast-as-possible + def count_number_of_lines(self,file_path): + lines = 0 + try: + with open(file_path, mode='r', encoding="utf-8", errors='ignore') as filename: + for _ in filename: + lines += 1 + except FileNotFoundError: + print('O Arquivo não existe!') + return f'{lines:,}'.replace(',','.') + + # https://stackoverflow.com/questions/436220/how-to-determine-the-encoding-of-text + # https://chardet.readthedocs.io/en/latest/usage.html + # https://github.com/PyYoshi/cChardet + # iconv -f WINDOWS-1252 -t UTF-8 filename.txt # iconv - convert text from one character encoding to another + def predict_encoding(self,file_path): + '''Predict a file's encoding using cchardet''' + # import cchardet as chardet + lines = [] + my_regex = rb"^\|9999\|\d+\|" # descartar informações após a linha que contém |9999| seguido por dígitos ; b'': binary mode + with open(file_path, mode='rb') as filename: # mode 'rb': open the file as binary data + for line in filename: + match_object = re.search(my_regex, line, flags=re.IGNORECASE) + if len(lines) > 2**8 or match_object: + #print(f'{file_path = } ; {line = }') + break + lines.append(line) + rawdata = b''.join(lines) + info = chardet.detect(rawdata) # {'encoding': 'UTF-8', 'confidence': 0.9900000095367432} + encoding = info['encoding'] + if encoding is None or not re.search('UTF-8', encoding, flags=re.IGNORECASE): + encoding = 'Latin-1' + return encoding + + @property + def find_all_files(self): + # https://www.mkyong.com/python/python-how-to-list-all-files-in-a-directory/ + # https://docs.python.org/3/library/glob.html + files = [f for f in glob.glob(self.root_path + '/' + f"**/*.{self.extension}", recursive = self.recursive)] + # How to use a variable inside a regular expression? + my_regex = f"{self.pattern}" # Literal String Interpolation, "f-strings". + for file_path in files: + # path.isfile: The easiest way to check if both a file exists and if it is a file. + # seen_file: Is there a more Pythonic way to prevent adding a duplicate to a list? + if not os.path.isfile(file_path) or file_path.casefold() in self.seen_file: + continue + match_pattern = re.search(my_regex, str(file_path), flags=re.IGNORECASE) + if match_pattern: + self.seen_file.add(file_path.casefold()) + self.informations.setdefault(file_path, {})['tipo'] = 'Arquivo' + return self.informations + + @property + def find_all_efd_contrib(self): + indice = 0 + # Calling one method from another within same class in Python + return self.find_all_efd(indice) + + @property + def find_all_efd_icmsipi(self): + indice = 1 + # Calling one method from another within same class in Python + return self.find_all_efd(indice) + + def find_all_efd(self,indice=0): + if not self.informations: # How do I check if a list/dict is empty? + self.find_all_files # Calling one method from another within same class in Python + regex_efd = ["PISCOFINS", "SPED-EFD"] + efd_type = ['EFD Contribuições', 'EFD ICMS_IPI'] + idx_nome = [8,6] + idx_data = [6,4] + idx_cnpj = [9,7] + for file_path in self.informations: + encode_info = None + if not re.search(regex_efd[indice], file_path, flags=re.IGNORECASE): + continue + # Ler apenas a primeira linha para obter encode_info + with open(file_path, mode='rb') as filename: # mode 'rb': open the file as binary data + for line in filename: + info = chardet.detect(line) # {'encoding': 'UTF-8', 'confidence': 0.9900000095367432} + encode_info = info['encoding'] + #print(f'{file_path = } ; {encode_info = } ; {info = }') + break + # Ler apenas a primeira linha para obter informações do registro de abertura '0000'. + with open(file_path, mode='r', encoding=encode_info, errors='ignore') as filename: # encoding='latin-1','UTF-8' + for line in filename: + campos = line.strip().split('|') + if len(campos) <= 10: + break + campo_registro = campos[1] # A primeira linha deve conter o registro '0000' + campo_nome = campos[ idx_nome[indice] ] + campo_data = campos[ idx_data[indice] ] + campo_cnpj = campos[ idx_cnpj[indice] ] # o campo CNPJ deve conter 14 dígitos + match_regi = re.search( '0000', campo_registro) + match_cnpj = re.search(r'(\D|^)\d{14}(\D|$)', campo_cnpj) + match_data = re.search(r'(\D|^)\d{8}(\D|$)', campo_data) + if match_regi and match_cnpj and match_data: + self.informations[file_path]['tipo'] = efd_type[indice] + self.informations[file_path]['NOME'] = campo_nome + self.informations[file_path]['CNPJ'] = "%s.%s.%s/%s-%s" % (campo_cnpj[0:2],campo_cnpj[2:5],campo_cnpj[5:8],campo_cnpj[8:12],campo_cnpj[12:14]) + self.informations[file_path]['DT_INI'] = "%s/%s/%s" % (campo_data[0:2],campo_data[2:4],campo_data[4:8]) + break + # Filter a Dictionary by values in Python using dict comprehension + return {key: value for (key, value) in sorted(self.informations.items()) if value['tipo'] == efd_type[indice]} + + def get_file_info(self,file_path): + self.informations[file_path]['extensão' ] = self.get_file_extension(file_path) + self.informations[file_path]['codificação' ] = self.predict_encoding(file_path) + self.informations[file_path]['número de linhas'] = self.count_number_of_lines(file_path) + return self.informations[file_path] + +from time import time, sleep + +def Total_Execution_Time(start,end=None): + ''' + How to format elapsed time from seconds to hours, minutes, seconds and milliseconds in Python? + https://stackoverflow.com/questions/27779677/how-to-format-elapsed-time-from-seconds-to-hours-minutes-seconds-and-milliseco + https://stackoverflow.com/questions/3620943/measuring-elapsed-time-with-the-time-module/46544199 + https://blog.softhints.com/python-test-performance-and-measure-time-elapsed-in-seconds/ + ''' + if end is None: + end = time() + hours, rem = divmod(end-start, 3600) + minutes, seconds = divmod(rem, 60) + return f"{int(hours):02d}h:{int(minutes):02d}m:{seconds:07.4f}s" + + +if __name__ == '__main__': + + start = time() + + #print(f'\n{ReadFiles.__dict__ = } \n') + + lista_de_arquivos0 = ReadFiles(root_path = '.') + lista_de_arquivos1 = ReadFiles(root_path = 'EFD Contribuicoes', extension = 'txt', pattern = 'PISCOFINS') + lista_de_arquivos2 = ReadFiles(root_path = 'EFD ICMS_IPI-ADM', extension = 'txt', pattern = 'SPED-EFD' ) + + arquivos_da_efd = [lista_de_arquivos0, lista_de_arquivos1, lista_de_arquivos2] + + for lista_de_arquivos in arquivos_da_efd: + print(f'\nlista_de_arquivos = {lista_de_arquivos}:\n') + + print(f'lista_de_arquivos.find_all_files = {lista_de_arquivos.find_all_files} ; len(lista_de_arquivos.informations) = {len(lista_de_arquivos.informations)}\n') + + # SPED EFD Contrib: + for index,file_path in enumerate(lista_de_arquivos.find_all_efd_contrib,1): + print( f"{index:>6}: {file_path} ; tipo = {lista_de_arquivos.informations[file_path]['tipo']}" ) + #continue + for attribute, value in lista_de_arquivos.get_file_info(file_path).items(): + print(f'{attribute:>30}: {value}') + + # SPED EFD ICMS_IPI: + for index,file_path in enumerate(lista_de_arquivos.find_all_efd_icmsipi,1): + print( f"{index:>6}: {file_path} ; tipo = {lista_de_arquivos.informations[file_path]['tipo']}" ) + #continue + for attribute, value in lista_de_arquivos.get_file_info(file_path).items(): + print(f'{attribute:>30}: {value}') + + end = time() + print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)} \n') + From e5a83235aebbfb15112d3c88601abae37bbd69ce Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:08:01 -0300 Subject: [PATCH 15/52] =?UTF-8?q?[new]=20execut=C3=A1vel=20para=20impress?= =?UTF-8?q?=C3=A3o=20de=20relat=C3=B3rios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_relatorios.py | 100 ++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100755 sped/relatorios/efd_relatorios.py diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py new file mode 100755 index 0000000..2d4a42e --- /dev/null +++ b/sped/relatorios/efd_relatorios.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' +Data = '14 de Fevereiro de 2020 (início: 29 de Janeiro de 2020)' + +# Instruções (no Linux): + +# Digite em seu web brawser o endereço abaixo: +# https://github.com/claudiofsr/python-sped +# Clique em 'Clone or download'. +# Em seguida, descompacte o arquivo copiado: +# > unzip python-sped-11.0.zip +# > cd python-sped-11.0 +# Para instalar o módulo do sped em seu sistema execute, como superusuário: +# python setup.py install +# Copie o arquivo 'efd_relatorios.py' de python-sped-11.0/relatorios +# para o diretório que contenha os arquivos de EFD Contribuições. +# Em seguida, execute no terminal o camando: +# > python efd_relatorios.py + +import sys, os +from time import time, sleep +from sped import __version__ +from sped.relatorios.efd_read_dir import ReadFiles, Total_Execution_Time +from sped.relatorios.efd_info import SPED_EFD_Info + +# Versão mínima exigida: python 3.6.0 +python_version = sys.version_info +if python_version < (3,6,0): + print('versão mínima exigida do python é 3.6.0') + print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) + exit() + +if __name__ == '__main__': + + print(f'\nPython Sped - versão: {__version__}\n') + + dir_path = os.getcwd() # CurrentDirectory + extensao = 'txt' + + lista_de_arquivos = ReadFiles(root_path = dir_path, extension = extensao) + + arquivos_efd_contrib = list(lista_de_arquivos.find_all_efd_contrib) # SPED EFD Contrib + arquivos_efd_icms_ipi = list(lista_de_arquivos.find_all_efd_icmsipi) # SPED EFD ICMS_IPI + + arquivos_sped_efd = arquivos_efd_contrib + arquivos_efd_icms_ipi + + for index,file_path in enumerate(arquivos_sped_efd,1): + print( f"{index:>6}: {file_path}") + for attribute, value in lista_de_arquivos.get_file_info(file_path).items(): + print(f'{attribute:>25}: {value}') + + indice_do_arquivo = None + + if len(arquivos_sped_efd) > 1: + while indice_do_arquivo is None: + my_input = input(f"\nFavor, digite o número do arquivo SPED EFD (1 a {len(arquivos_sped_efd)}): ") + try: + my_input = int(my_input) + if 1 <= my_input <= len(arquivos_sped_efd): + indice_do_arquivo = my_input - 1 + except: + print(f"-->Opção incorreta: '{my_input}'.") + print(f"-->Digite um número inteiro entre 1 e {len(arquivos_sped_efd)}.") + elif len(arquivos_sped_efd) == 1: + indice_do_arquivo = 0 + else: + dir_path_exemplo = '/home/claudio/Documentos/' + print(f"A lista de arquivos de SPED EFD é obtida a partir de:\n") + print(f"\tlista_de_arquivos = ReadFiles(root_path = dir_path, extension = extensao).\n") + print(f"tal que:\n") + print(f"\tdir_path = '{dir_path}' e extensao = '{extensao}'.\n") + print(f"Nenhum arquivo de SPED EFD foi encontrado no diretório dir_path definido acima.") + print(f"Se as EFDs estão localizadas, por exemplo, no diretório '{dir_path_exemplo}',") + print(f"então altere a variável 'dir_path' para o diretório que contenha as EFDs:") + print(f"\n\tdir_path = '{dir_path_exemplo}'\n") + print(f"Outra alternativa é copiar este arquivo '{__file__}' para o diretório que contenha as EFDs.") + print(f"Em seguida, executar no terminal:\n") + print(f"\t python {__file__} \n") + exit() + + # arquivo SPED EFD + file_path = arquivos_sped_efd[indice_do_arquivo] + tipo_da_efd = lista_de_arquivos.informations[file_path]['tipo'] + codificacao = lista_de_arquivos.informations[file_path]['codificação'] + + print(f"\nFoi selecionado o arquivo {indice_do_arquivo + 1}: '{file_path}'\n") + input("Tecle Enter para gerar arquivo .csv com informações da EFD ") + print() + + start = time() + + efd = SPED_EFD_Info(file_path, encoding=codificacao, efd_tipo = tipo_da_efd, verbose=False) + + efd.imprimir_informacoes + + end = time() + + print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)} \n') + From 0de32d5ea050bd174c96a22b4f0da54d64cc7463 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:08:59 -0300 Subject: [PATCH 16/52] [new] tabelas adotadas --- sped/relatorios/efd_tabelas.py | 959 +++++++++++++++++++++++++++++++++ 1 file changed, 959 insertions(+) create mode 100644 sped/relatorios/efd_tabelas.py diff --git a/sped/relatorios/efd_tabelas.py b/sped/relatorios/efd_tabelas.py new file mode 100644 index 0000000..868ee19 --- /dev/null +++ b/sped/relatorios/efd_tabelas.py @@ -0,0 +1,959 @@ +# -*- coding: utf-8 -*- + +Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' +Data = '21 de Fevereiro de 2020 (início: 10 de Janeiro de 2020)' + +class EFD_Tabelas: + """ + Tabelas utilizadas na EFD + """ + + tabela_mes_nominal = { + '01': 'Janeiro', + '02': 'Fevereiro', + '03': 'Março', + '04': 'Abril', + '05': 'Maio', + '06': 'Junho', + '07': 'Julho', + '08': 'Agosto', + '09': 'Setembro', + '10': 'Outubro', + '11': 'Novembro', + '12': 'Dezembro', + } + + tabela_natureza_da_conta = { + '01': 'Contas de ativo', + '02': 'Contas de passivo', + '03': 'Patrimônio líquido', + '04': 'Contas de resultado', + '05': 'Contas de compensação', + '09': 'Outras', + } + + # Fonte: GUIA PRÁTICO DA EFD Contribuicoes - PIS e COFINS + tabela_info_do_registro = { + '0': 'Abertura, Identificação e Referências', + 'A': 'Serviços (ISS): Serviços Prestados ou Contratados', + 'B': 'Escrituração e Apuração do ISS', + 'C': 'Mercadorias (ICMS/IPI): Venda e Aquisição de Mercadorias e Produtos', + 'D': 'Serviços (ICMS): Venda e Aquisição de Serviços de Transportes e de (Tele)comunicação', + 'E': 'Apuração do ICMS e do IPI', + 'F': 'Demais Documentos e Operações', + 'G': 'Controle do Crédito de ICMS do Ativo Permanente – CIAP', + 'H': 'Inventário Físico', + 'I': 'Instituições Financeiras e Assemelhadas, Seguradoras, Entidades de Previdência Privada e Operadoras de Planos de Assistência à Saúde', + 'K': 'Controle da Produção e do Estoque', + 'M': 'Apuração da Contribuição e Crédito de PIS/PASEP e da COFINS', + 'P': 'Apuração da Contribuição Previdenciária sobre a Receita Bruta', + '1': 'Complemento da Escrituração', + '9': 'Controle e Encerramento do Arquivo Digital', + # descrição mais específica: + 'C185': 'Operações de Vendas - NFe e NFCe Consolidadas', + 'C195': 'Operações de Aquisição com Crédito e Operações de Devolução - NFes Consolidadas', + 'C385': 'Nota Fiscal de Venda a Consumidor - Documentos Consolidados', + 'C485': 'Resumo Diário de Documentos Emitidos por ECF', + 'C495': 'Detalhamento da Consolidação de Documentos Emitidos por ECF', + 'C505': 'Energia Elétrica, Água Canalizada ou Gás utilizados como insumo', + 'F100': 'Demais Receitas Auferidas / Outras Operações com Direito a Crédito', + 'F120': 'Bens Incorporados ao Ativo Imobilizado - créditos sobre depreciação e amortização', + 'F130': 'Bens Incorporados ao Ativo Imobilizado - créditos com base no valor de aquisição', + 'F150': 'Crédito Presumido sobre Estoque de Abertura', + 'F200': 'Operações da Atividade Imobiliária - Unidade Imobiliária Vendida', + } + + # Tabela 4.3.7 - Tabela Código de Base de Cálculo do Crédito + tabela_bc_do_credito = { + '01': 'Aquisição de bens para revenda', + '02': 'Aquisição de bens utilizados como insumo', + '03': 'Aquisição de serviços utilizados como insumo', + '04': 'Energia elétrica e térmica, inclusive sob a forma de vapor', + '05': 'Aluguéis de prédios', + '06': 'Aluguéis de máquinas e equipamentos', + '07': 'Armazenagem de mercadoria e frete na operação de venda', + '08': 'Contraprestações de arrendamento mercantil', + '09': 'Máquinas, equipamentos e outros bens incorporados ao ativo imobilizado (crédito sobre encargos de depreciação)', + '10': 'Máquinas, equipamentos e outros bens incorporados ao ativo imobilizado (crédito com base no valor de aquisição)', + '11': 'Amortização e Depreciação de edificações e benfeitorias em imóveis', + '12': 'Devolução de Vendas Sujeitas à Incidência Não-Cumulativa', + '13': 'Outras Operações com Direito a Crédito', + '14': 'Atividade de Transporte de Cargas - Subcontratação', + '15': 'Atividade Imobiliária - Custo Incorrido de Unidade Imobiliária', + '16': 'Atividade Imobiliária - Custo Orçado de unidade não concluída', + '17': 'Atividade de Prestação de Serviços de Limpeza, Conservação e Manutenção - vale-transporte, valerefeição ou vale-alimentação, fardamento ou uniforme', + '18': 'Estoque de abertura de bens', + } + + # 4.3.3 - CÓDIGO DA SITUAÇÃO TRIBUTÁRIA REFERENTE AO PIS/PASEP e COFINS + tabela_cst_contrib = { + '01': 'Operação Tributável com Alíquota Básica', + '02': 'Operação Tributável com Alíquota Diferenciada', + '03': 'Operação Tributável com Alíquota por Unidade de Medida de Produto', + '04': 'Operação Tributável Monofásica - Revenda a Alíquota Zero', + '05': 'Operação Tributável por Substituição Tributária', + '06': 'Operação Tributável a Alíquota Zero', + '07': 'Operação Isenta da Contribuição', + '08': 'Operação sem Incidência da Contribuição', + '09': 'Operação com Suspensão da Contribuição', + '49': 'Outras Operações de Saída', + '50': 'Operação com Direito a Crédito - Vinculada Exclusivamente a Receita Tributada no Mercado Interno', + '51': 'Operação com Direito a Crédito - Vinculada Exclusivamente a Receita Não Tributada no Mercado Interno', + '52': 'Operação com Direito a Crédito - Vinculada Exclusivamente a Receita de Exportação', + '53': 'Operação com Direito a Crédito - Vinculada a Receitas Tributadas e Não-Tributadas no Mercado Interno', + '54': 'Operação com Direito a Crédito - Vinculada a Receitas Tributadas no Mercado Interno e de Exportação', + '55': 'Operação com Direito a Crédito - Vinculada a Receitas Não-Tributadas no Mercado Interno e de Exportação', + '56': 'Operação com Direito a Crédito - Vinculada a Receitas Tributadas e Não-Tributadas no Mercado Interno, e de Exportação', + '60': 'Crédito Presumido - Operação de Aquisição Vinculada Exclusivamente a Receita Tributada no Mercado Interno', + '61': 'Crédito Presumido - Operação de Aquisição Vinculada Exclusivamente a Receita Não-Tributada no Mercado Interno', + '62': 'Crédito Presumido - Operação de Aquisição Vinculada Exclusivamente a Receita de Exportação', + '63': 'Crédito Presumido - Operação de Aquisição Vinculada a Receitas Tributadas e Não-Tributadas no Mercado Interno', + '64': 'Crédito Presumido - Operação de Aquisição Vinculada a Receitas Tributadas no Mercado Interno e de Exportação', + '65': 'Crédito Presumido - Operação de Aquisição Vinculada a Receitas Não-Tributadas no Mercado Interno e de Exportação', + '66': 'Crédito Presumido - Operação de Aquisição Vinculada a Receitas Tributadas e Não-Tributadas no Mercado Interno, e de Exportação', + '67': 'Crédito Presumido - Outras Operações', + '70': 'Operação de Aquisição sem Direito a Crédito', + '71': 'Operação de Aquisição com Isenção', + '72': 'Operação de Aquisição com Suspensão', + '73': 'Operação de Aquisição a Alíquota Zero', + '74': 'Operação de Aquisição sem Incidência da Contribuição', + '75': 'Operação de Aquisição por Substituição Tributária', + '98': 'Outras Operações de Entrada', + '99': 'Outras Operações', + } + + # Tabela Código da Situação Tributária - CST (ICMS) (Pacote: Tabelas de Situação Tributária) + # Versão 3, somente códigos vigentes. + tabela_cst_icms = { + '000': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Tributada integralmente', + '010': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Tributada e com cobrança do ICMS por substituição tributária', + '020': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Com redução de base de cálculo', + '030': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '040': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Isenta', + '041': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Não tributada', + '050': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Suspensão', + '051': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Diferimento', + '060': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - ICMS cobrado anteriormente por substituição tributária', + '070': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '090': 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8 da Tabela A - Outras', + '100': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Tributada integralmente', + '101': 'Simples Nacional - Tributada pelo Simples Nacional com permissão de crédito', + '102': 'Simples Nacional - Tributada pelo Simples Nacional sem permissão de crédito', + '103': 'Simples Nacional - Isenção do ICMS no Simples Nacional para faixa de receita bruta', + '110': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Tributada e com cobrança do ICMS por substituição tributária', + '120': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Com redução de base de cálculo', + '130': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '140': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Isenta', + '141': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Não tributada', + '150': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Suspensão', + '151': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Diferimento', + '160': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - ICMS cobrado anteriormente por substituição tributária', + '170': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '190': 'Estrangeira - Importação direta, exceto a indicada no código 6 da Tabela A - Outras', + '200': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Tributada integralmente', + '201': 'Simples Nacional - Tributada pelo Simples Nacional com permissão de crédito e com cobrança do ICMS por substituição tributária', + '202': 'Simples Nacional - Tributada pelo Simples Nacional sem permissão de crédito e com cobrança do ICMS por substituição tributária', + '203': 'Simples Nacional - Isenção do ICMS no Simples Nacional para faixa de receita bruta e com cobrança do ICMS por substituição tributária', + '210': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Tributada e com cobrança do ICMS por substituição tributária', + '220': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Com redução de base de cálculo', + '230': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '240': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Isenta', + '241': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Não tributada', + '250': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Suspensão', + '251': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Diferimento', + '260': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - ICMS cobrado anteriormente por substituição tributária', + '270': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '290': 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7 da Tabela A - Outras', + '300': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Tributada integralmente', + '310': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Tributada e com cobrança do ICMS por substituição tributária', + '320': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Com redução de base de cálculo', + '330': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '340': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Isenta', + '341': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Não tributada', + '350': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Suspensão', + '351': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Diferimento', + '360': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - ICMS cobrado anteriormente por substituição tributária', + '370': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '390': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 40% (quarenta por cento) e inferior ou igual a 70% (setenta por cento) - Outras', + '400': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/07 - Tributada integralmente', + '410': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/08 - Tributada e com cobrança do ICMS por substituição tributária', + '420': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/09 - Com redução de base de cálculo', + '430': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/10 - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '440': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/11 - Isenta', + '441': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/12 - Não tributada', + '450': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/13 - Suspensão', + '451': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/14 - Diferimento', + '460': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/15 - ICMS cobrado anteriormente por substituição tributária', + '470': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/16 - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '490': 'Nacional, cuja produção tenha sido feita em conformidade com os processos produtivos básicos de que tratam o Decreto-Lei nº 288/67, e as Leis nºs 8.248/91, 8.387/91, 10.176/01 e 11.484/17 - Outras', + '500': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Tributada integralmente', + '510': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Tributada e com cobrança do ICMS por substituição tributária', + '520': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Com redução de base de cálculo', + '530': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '540': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Isenta', + '541': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Não tributada', + '550': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Suspensão', + '551': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Diferimento', + '560': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - ICMS cobrado anteriormente por substituição tributária', + '570': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '590': 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40% (quarenta por cento) - Outras', + '600': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Tributada integralmente', + '610': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Tributada e com cobrança do ICMS por substituição tributária', + '620': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Com redução de base de cálculo', + '630': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '640': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Isenta', + '641': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Não tributada', + '650': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Suspensão', + '651': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Diferimento', + '660': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - ICMS cobrado anteriormente por substituição tributária', + '670': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '690': 'Estrangeira - Importação direta, sem similar nacional, constante em lista de Resolução CAMEX - Outras', + '700': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Tributada integralmente', + '710': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Tributada e com cobrança do ICMS por substituição tributária', + '720': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Com redução de base de cálculo', + '730': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '740': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Isenta', + '741': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Não tributada', + '750': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Suspensão', + '751': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Diferimento', + '760': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - ICMS cobrado anteriormente por substituição tributária', + '770': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '790': 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista de Resolução CAMEX - Outras', + '800': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Tributada integralmente', + '810': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Tributada e com cobrança do ICMS por substituição tributária', + '820': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Com redução de base de cálculo', + '830': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Isenta ou não tributada e com cobrança do ICMS por substituição tributária', + '840': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Isenta', + '841': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Não tributada', + '850': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Suspensão', + '851': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Diferimento', + '860': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - ICMS cobrado anteriormente por substituição tributária', + '870': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Com redução de base de cálculo e cobrança do ICMS por substituição tributária', + '890': 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70% (setenta por cento) - Outras', + '900': 'Simples Nacional - Outros', + } + + tabela_tipo_do_item = { + '00': 'Mercadoria para Revenda', + '01': 'Matéria-Prima', + '02': 'Embalagem', + '03': 'Produto em Processo', + '04': 'Produto Acabado', + '05': 'Subproduto', + '06': 'Produto Intermediário', + '07': 'Material de Uso e Consumo', + '08': 'Ativo Imobilizado', + '09': 'Serviços', + '10': 'Outros insumos', + '99': 'Outras', + } + + # Tabela 4.1.1: Modelos de documentos fiscais e registros correspondentes na EFD-Contribuições + tabela_modelos_documentos_fiscais = { + '01': 'Nota Fiscal', + '1B': 'Nota Fiscal Avulsa', + '02': 'Nota Fiscal de Venda a Consumidor', + '2D': 'Cupom Fiscal emitido por ECF', + '2E': 'Bilhete de Passagem emitido por ECF', + '04': 'Nota Fiscal de Produtor', + '06': 'Nota Fiscal / Conta de Energia Elétrica', + '07': 'Nota Fiscal de Serviço de Transporte', + '08': 'Conhecimento de Transporte Rodoviário de Cargas', + '8B': 'Conhecimento de Transporte de Cargas Avulso', + '09': 'Conhecimento de Transporte Aquaviário de Cargas', + '10': 'Conhecimento Aéreo', + '11': 'Conhecimento de Transporte Ferroviário de Cargas', + '13': 'Bilhete de Passagem Rodoviário', + '14': 'Bilhete de Passagem Aquaviário', + '15': 'Bilhete de Passagem e Nota de Bagagem', + '17': 'Despacho de Transporte', + '16': 'Bilhete de Passagem Ferroviário', + '18': 'Resumo de Movimento Diário', + '20': 'Ordem de Coleta de Cargas', + '21': 'Nota Fiscal de Serviço de Comunicação', + '22': 'Nota Fiscal de Serviço de Telecomunicação', + '23': 'GNRE', + '24': 'Autorização de Carregamento e Transporte', + '25': 'Manifesto de Carga', + '26': 'Conhecimento de Transporte Multimodal de Cargas', + '27': 'Nota Fiscal de Transporte Ferroviário de Cargas', + '28': 'Nota Fiscal / Conta de Fornecimento de Gás Canalizado', + '29': 'Nota Fiscal / Conta de Fornecimento de Água Canalizada', + '30': 'Bilhete / Recibo do Passageiro', + '55': 'Nota Fiscal Eletrônica: NF-e', + '57': 'Conhecimento de Transporte Eletrônico: CT-e', + '59': 'Cupom Fiscal Eletrônico: CF-e-SAT', + '60': 'Cupom Fiscal Eletrônico: CF-e-ECF', + '63': 'Bilhete de Passagem Eletrônico: BP-e', + '65': 'Nota Fiscal Eletrônica ao Consumidor Final: NFC-e', + '66': 'Nota Fiscal de Energia Elétrica Eletrônica: NF3e', + '67': 'Conhecimento de Transporte Eletrônico para Outros Serviços: CT-e OS', + } + + # Tabela Código CFOP: Descrição Resumida + # https://www.confaz.fazenda.gov.br/legislacao/ajustes/sinief/cfop_cvsn_70_vigente + # ^(\d{4}) - (.*)$ | '$1': '$2', + + tabela_cfop_descricao = { + '1000': 'ENTRADAS OU AQUISIÇÕES DE SERVIÇOS DO ESTADO', + '1100': 'COMPRAS PARA INDUSTRIALIZAÇÃO, PRODUÇÃO RURAL, COMERCIALIZAÇÃO OU PRESTAÇÃO DE SERVIÇOS', + '1101': 'Compra para industrialização ou produção rural', + '1102': 'Compra para comercialização', + '1111': 'Compra para industrialização de mercadoria recebida anteriormente em consignação industrial', + '1113': 'Compra para comercialização, de mercadoria recebida anteriormente em consignação mercantil', + '1116': 'Compra para industrialização ou produção rural originada de encomenda para recebimento futuro', + '1117': 'Compra para comercialização originada de encomenda para recebimento futuro', + '1118': 'Compra de mercadoria para comercialização pelo adquirente originário, entregue pelo vendedor remetente ao destinatário, em venda à ordem', + '1120': 'Compra para industrialização, em venda à ordem, já recebida do vendedor remetente', + '1121': 'Compra para comercialização, em venda à ordem, já recebida do vendedor remetente', + '1122': 'Compra para industrialização em que a mercadoria foi remetida pelo fornecedor ao industrializador sem transitar pelo estabelecimento adquirente', + '1124': 'Industrialização efetuada por outra empresa', + '1125': 'Industrialização efetuada por outra empresa quando a mercadoria remetida para utilização no processo de industrialização não transitou pelo estabelecimento adquirente da mercadoria', + '1126': 'Compra para utilização na prestação de serviço sujeita ao ICMS', + '1128': 'Compra para utilização na prestação de serviço sujeita ao ISSQN', + '1131': 'Entrada de mercadoria com previsão de posterior ajuste ou fixação de preço, decorrente de operação de ato cooperativo.', + '1132': 'Fixação de preço de produção do estabelecimento produtor, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço, em ato cooperativo, para comercialização.', + '1135': 'Fixação de preço de produção do estabelecimento produtor, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço, em ato cooperativo, para industrialização.', + '1150': 'TRANSFERÊNCIAS PARA INDUSTRIALIZAÇÃO, PRODUÇÃO RURAL, COMERCIALIZAÇÃO OU PRESTAÇÃO DE SERVIÇOS', + '1151': 'Transferência para industrialização ou produção rural', + '1152': 'Transferência para comercialização', + '1153': 'Transferência de energia elétrica para distribuição', + '1154': 'Transferência para utilização na prestação de serviço', + '1159': 'Entrada decorrente do fornecimento de produto ou mercadoria de ato cooperativo', + '1200': 'DEVOLUÇÕES DE VENDAS DE PRODUÇÃO PRÓPRIA, DE TERCEIROS OU ANULAÇÕES DE VALORES', + '1201': 'Devolução de venda de produção do estabelecimento', + '1202': 'Devolução de venda de mercadoria adquirida ou recebida de terceiros', + '1203': 'Devolução de venda de produção do estabelecimento, destinada à Zona Franca de Manaus ou Áreas de Livre Comércio', + '1204': 'Devolução de venda de mercadoria adquirida ou recebida de terceiros, destinada à Zona Franca de Manaus ou Áreas de Livre Comércio', + '1205': 'Anulação de valor relativo à prestação de serviço de comunicação', + '1206': 'Anulação de valor relativo à prestação de serviço de transporte', + '1207': 'Anulação de valor relativo à venda de energia elétrica', + '1208': 'Devolução de produção do estabelecimento, remetida em transferência', + '1209': 'Devolução de mercadoria adquirida ou recebida de terceiros, remetida em transferência', + '1212': 'Devolução de venda no mercado interno de mercadoria industrializada e insumo importado sob o Regime Aduaneiro Especial de Entreposto Industrial sob Controle Informatizado do Sistema Público de Escrituração Digital (Recof-Sped).', + '1213': 'Devolução de remessa de produção do estabelecimento com previsão de posterior ajuste ou fixação de preço, em ato cooperativo.', + '1214': 'Devolução de fixação de preço de produção do estabelecimento produtor, de ato cooperativo.', + '1250': 'COMPRAS DE ENERGIA ELÉTRICA', + '1251': 'Compra de energia elétrica para distribuição ou comercialização', + '1252': 'Compra de energia elétrica por estabelecimento industrial', + '1253': 'Compra de energia elétrica por estabelecimento comercial', + '1254': 'Compra de energia elétrica por estabelecimento prestador de serviço de transporte', + '1255': 'Compra de energia elétrica por estabelecimento prestador de serviço de comunicação', + '1256': 'Compra de energia elétrica por estabelecimento de produtor rural', + '1257': 'Compra de energia elétrica para consumo por demanda contratada', + '1300': 'AQUISIÇÕES DE SERVIÇOS DE COMUNICAÇÃO', + '1301': 'Aquisição de serviço de comunicação para execução de serviço da mesma natureza', + '1302': 'Aquisição de serviço de comunicação por estabelecimento industrial', + '1303': 'Aquisição de serviço de comunicação por estabelecimento comercial', + '1304': 'Aquisição de serviço de comunicação por estabelecimento de prestador de serviço de transporte', + '1305': 'Aquisição de serviço de comunicação por estabelecimento de geradora ou de distribuidora de energia elétrica', + '1306': 'Aquisição de serviço de comunicação por estabelecimento de produtor rural', + '1350': 'AQUISIÇÕES DE SERVIÇOS DE TRANSPORTE', + '1351': 'Aquisição de serviço de transporte para execução de serviço da mesma natureza', + '1352': 'Aquisição de serviço de transporte por estabelecimento industrial', + '1353': 'Aquisição de serviço de transporte por estabelecimento comercial', + '1354': 'Aquisição de serviço de transporte por estabelecimento de prestador de serviço de comunicação', + '1355': 'Aquisição de serviço de transporte por estabelecimento de geradora ou de distribuidora de energia elétrica', + '1356': 'Aquisição de serviço de transporte por estabelecimento de produtor rural', + '1360': 'Aquisição de serviço de transporte por contribuinte substituto em relação ao serviço de transporte', + '1400': 'ENTRADAS DE MERCADORIAS SUJEITAS AO REGIME DE SUBSTITUIÇÃO TRIBUTÁRIA', + '1401': 'Compra para industrialização ou produção rural em operação com mercadoria sujeita ao regime de substituição tributária', + '1403': 'Compra para comercialização em operação com mercadoria sujeita ao regime de substituição tributária', + '1406': 'Compra de bem para o ativo imobilizado cuja mercadoria está sujeita ao regime de substituição tributária', + '1407': 'Compra de mercadoria para uso ou consumo cuja mercadoria está sujeita ao regime de substituição tributária', + '1408': 'Transferência para industrialização ou produção rural em operação com mercadoria sujeita ao regime de substituição tributária', + '1409': 'Transferência para comercialização em operação com mercadoria sujeita ao regime de substituição tributária', + '1410': 'Devolução de venda de produção do estabelecimento em operação com produto sujeito ao regime de substituição tributária', + '1411': 'Devolução de venda de mercadoria adquirida ou recebida de terceiros em operação com mercadoria sujeita ao regime de substituição tributária', + '1414': 'Retorno de produção do estabelecimento, remetida para venda fora do estabelecimento em operação com produto sujeito ao regime de substituição tributária', + '1415': 'Retorno de mercadoria adquirida ou recebida de terceiros, remetida para venda fora do estabelecimento em operação com mercadoria sujeita ao regime de substituição tributária', + '1450': 'SISTEMAS DE INTEGRAÇÃO', + '1451': 'Retorno de animal do estabelecimento produtor', + '1452': 'Retorno de insumo não utilizado na produção', + '1500': 'ENTRADAS DE MERCADORIAS REMETIDAS PARA FORMAÇÃO DE LOTE OU COM FIM ESPECÍFICO DE EXPORTAÇÃO E EVENTUAIS DEVOLUÇÕES', + '1501': 'Entrada de mercadoria recebida com fim específico de exportação', + '1503': 'Entrada decorrente de devolução de produto remetido com fim específico de exportação, de produção do estabelecimento', + '1504': 'Entrada decorrente de devolução de mercadoria remetida com fim específico de exportação, adquirida ou recebida de terceiros', + '1505': 'Entrada decorrente de devolução de mercadorias remetidas para formação de lote de exportação, de produtos industrializados ou produzidos pelo próprio estabelecimento', + '1506': 'Entrada decorrente de devolução de mercadorias, adquiridas ou recebidas de terceiros, remetidas para formação de lote de exportação', + '1550': 'OPERAÇÕES COM BENS DE ATIVO IMOBILIZADO E MATERIAIS PARA USO OU CONSUMO', + '1551': 'Compra de bem para o ativo imobilizado', + '1552': 'Transferência de bem do ativo imobilizado', + '1553': 'Devolução de venda de bem do ativo imobilizado', + '1554': 'Retorno de bem do ativo imobilizado remetido para uso fora do estabelecimento', + '1555': 'Entrada de bem do ativo imobilizado de terceiro, remetido para uso no estabelecimento', + '1556': 'Compra de material para uso ou consumo', + '1557': 'Transferência de material para uso ou consumo', + '1600': 'CRÉDITOS E RESSARCIMENTOS DE ICMS', + '1601': 'Recebimento, por transferência, de crédito de ICMS', + '1602': 'Recebimento, por transferência, de saldo credor de ICMS de outro estabelecimento da mesma empresa, para compensação de saldo devedor de ICMS', + '1603': 'Ressarcimento de ICMS retido por substituição tributária', + '1604': 'Lançamento do crédito relativo à compra de bem para o ativo imobilizado', + '1605': 'Recebimento, por transferência, de saldo devedor de ICMS de outro estabelecimento da mesma empresa.', + '1650': 'ENTRADAS DE COMBUSTÍVEIS, DERIVADOS OU NÃO DE PETRÓLEO E LUBRIFICANTES', + '1651': 'Compra de combustível ou lubrificante para industrialização subseqüente', + '1652': 'Compra de combustível ou lubrificante para comercialização', + '1653': 'Compra de combustível ou lubrificante por consumidor ou usuário final', + '1658': 'Transferência de combustível e lubrificante para industrialização', + '1659': 'Transferência de combustível e lubrificante para comercialização', + '1660': 'Devolução de venda de combustível ou lubrificante destinado à industrialização subseqüente', + '1661': 'Devolução de venda de combustível ou lubrificante destinado à comercialização', + '1662': 'Devolução de venda de combustível ou lubrificante destinado a consumidor ou usuário final', + '1663': 'Entrada de combustível ou lubrificante para armazenagem', + '1664': 'Retorno de combustível ou lubrificante remetido para armazenagem', + '1900': 'OUTRAS ENTRADAS DE MERCADORIAS OU AQUISIÇÕES DE SERVIÇOS', + '1901': 'Entrada para industrialização por encomenda', + '1902': 'Retorno de mercadoria remetida para industrialização por encomenda', + '1903': 'Entrada de mercadoria remetida para industrialização e não aplicada no referido processo', + '1904': 'Retorno de remessa para venda fora do estabelecimento', + '1905': 'Entrada de mercadoria recebida para depósito em depósito fechado ou armazém geral', + '1906': 'Retorno de mercadoria remetida para depósito fechado ou armazém geral', + '1907': 'Retorno simbólico de mercadoria remetida para depósito fechado ou armazém geral', + '1908': 'Entrada de bem por conta de contrato de comodato', + '1909': 'Retorno de bem remetido por conta de contrato de comodato', + '1910': 'Entrada de bonificação, doação ou brinde', + '1911': 'Entrada de amostra grátis', + '1912': 'Entrada de mercadoria ou bem recebido para demonstração ou mostruário.', + '1913': 'Retorno de mercadoria ou bem remetido para demonstração, mostruário ou treinamento.', + '1914': 'Retorno de mercadoria ou bem remetido para exposição ou feira', + '1915': 'Entrada de mercadoria ou bem recebido para conserto ou reparo', + '1916': 'Retorno de mercadoria ou bem remetido para conserto ou reparo', + '1917': 'Entrada de mercadoria recebida em consignação mercantil ou industrial', + '1918': 'Devolução de mercadoria remetida em consignação mercantil ou industrial', + '1919': 'Devolução simbólica de mercadoria vendida ou utilizada em processo industrial, remetida anteriormente em consignação mercantil ou industrial', + '1920': 'Entrada de vasilhame ou sacaria', + '1921': 'Retorno de vasilhame ou sacaria', + '1922': 'Lançamento efetuado a título de simples faturamento decorrente de compra para recebimento futuro', + '1923': 'Entrada de mercadoria recebida do vendedor remetente, em venda à ordem', + '1924': 'Entrada para industrialização por conta e ordem do adquirente da mercadoria, quando esta não transitar pelo estabelecimento do adquirente', + '1925': 'Retorno de mercadoria remetida para industrialização por conta e ordem do adquirente da mercadoria, quando esta não transitar pelo estabelecimento do adquirente', + '1926': 'Lançamento efetuado a título de reclassificação de mercadoria decorrente de formação de kit ou de sua desagregação', + '1931': 'Lançamento efetuado pelo tomador do serviço de transporte quando a responsabilidade de retenção do imposto for atribuída ao remetente ou alienante da mercadoria, pelo serviço de transporte realizado por transportador autônomo ou por transportador não inscrito na unidade da Federação onde iniciado o serviço.', + '1932': 'Aquisição de serviço de transporte iniciado em unidade da Federação diversa daquela onde inscrito o prestador.', + '1933': 'Aquisição de serviço tributado pelo ISSQN', + '1934': 'Entrada simbólica de mercadoria recebida para depósito fechado ou armazém geral', + '1949': 'Outra entrada de mercadoria ou prestação de serviço não especificada', + '2000': 'ENTRADAS OU AQUISIÇÕES DE SERVIÇOS DE OUTROS ESTADOS', + '2100': 'COMPRAS PARA INDUSTRIALIZAÇÃO, PRODUÇÃO RURAL, COMERCIALIZAÇÃO OU PRESTAÇÃO DE SERVIÇOS', + '2101': 'Compra para industrialização ou produção rural', + '2102': 'Compra para comercialização', + '2111': 'Compra para industrialização de mercadoria recebida anteriormente em consignação industrial', + '2113': 'Compra para comercialização, de mercadoria recebida anteriormente em consignação mercantil', + '2116': 'Compra para industrialização ou produção rural originada de encomenda para recebimento futuro', + '2117': 'Compra para comercialização originada de encomenda para recebimento futuro', + '2118': 'Compra de mercadoria para comercialização pelo adquirente originário, entregue pelo vendedor remetente ao destinatário, em venda à ordem', + '2120': 'Compra para industrialização, em venda à ordem, já recebida do vendedor remetente', + '2121': 'Compra para comercialização, em venda à ordem, já recebida do vendedor remetente', + '2122': 'Compra para industrialização em que a mercadoria foi remetida pelo fornecedor ao industrializador sem transitar pelo estabelecimento adquirente', + '2124': 'Industrialização efetuada por outra empresa', + '2125': 'Industrialização efetuada por outra empresa quando a mercadoria remetida para utilização no processo de industrialização não transitou pelo estabelecimento adquirente da mercadoria', + '2126': 'Compra para utilização na prestação de serviço sujeita ao ICMS', + '2128': 'Compra para utilização na prestação de serviço sujeita ao ISSQN', + '2131': 'Entrada de mercadoria com previsão de posterior ajuste ou fixação de preço, decorrente de operação de ato cooperativo.', + '2132': 'Fixação de preço de produção do estabelecimento produtor, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço, em ato cooperativo, para comercialização.', + '2135': 'Fixação de preço de produção do estabelecimento produtor, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço, em ato cooperativo, para industrialização.', + '2150': 'TRANSFERÊNCIAS PARA INDUSTRIALIZAÇÃO, PRODUÇÃO RURAL, COMERCIALIZAÇÃO OU PRESTAÇÃO DE SERVIÇOS', + '2151': 'Transferência para industrialização ou produção rural', + '2152': 'Transferência para comercialização', + '2153': 'Transferência de energia elétrica para distribuição', + '2154': 'Transferência para utilização na prestação de serviço', + '2159': 'Entrada decorrente do fornecimento de produto ou mercadoria de ato cooperativo', + '2200': 'DEVOLUÇÕES DE VENDAS DE PRODUÇÃO PRÓPRIA, DE TERCEIROS OU ANULAÇÕES DE VALORES', + '2201': 'Devolução de venda de produção do estabelecimento', + '2202': 'Devolução de venda de mercadoria adquirida ou recebida de terceiros', + '2203': 'Devolução de venda de produção do estabelecimento, destinada à Zona Franca de Manaus ou Áreas de Livre Comércio', + '2204': 'Devolução de venda de mercadoria adquirida ou recebida de terceiros, destinada à Zona Franca de Manaus ou Áreas de Livre Comércio', + '2205': 'Anulação de valor relativo à prestação de serviço de comunicação', + '2206': 'Anulação de valor relativo à prestação de serviço de transporte', + '2207': 'Anulação de valor relativo à venda de energia elétrica', + '2208': 'Devolução de produção do estabelecimento, remetida em transferência', + '2209': 'Devolução de mercadoria adquirida ou recebida de terceiros, remetida em transferência', + '2212': 'Devolução de venda no mercado interno de mercadoria industrializada e insumo importado sob o Regime Aduaneiro Especial de Entreposto Industrial sob Controle Informatizado do Sistema Público de Escrituração Digital (Recof-Sped).', + '2213': 'Devolução de remessa de produção do estabelecimento com previsão de posterior ajuste ou fixação de preço, em ato cooperativo.', + '2214': 'Devolução de fixação de preço de produção do estabelecimento produtor, de ato cooperativo.', + '2250': 'COMPRAS DE ENERGIA ELÉTRICA', + '2251': 'Compra de energia elétrica para distribuição ou comercialização', + '2252': 'Compra de energia elétrica por estabelecimento industrial', + '2253': 'Compra de energia elétrica por estabelecimento comercial', + '2254': 'Compra de energia elétrica por estabelecimento prestador de serviço de transporte', + '2255': 'Compra de energia elétrica por estabelecimento prestador de serviço de comunicação', + '2256': 'Compra de energia elétrica por estabelecimento de produtor rural', + '2257': 'Compra de energia elétrica para consumo por demanda contratada', + '2300': 'AQUISIÇÕES DE SERVIÇOS DE COMUNICAÇÃO', + '2301': 'Aquisição de serviço de comunicação para execução de serviço da mesma natureza', + '2302': 'Aquisição de serviço de comunicação por estabelecimento industrial', + '2303': 'Aquisição de serviço de comunicação por estabelecimento comercial', + '2304': 'Aquisição de serviço de comunicação por estabelecimento de prestador de serviço de transporte', + '2305': 'Aquisição de serviço de comunicação por estabelecimento de geradora ou de distribuidora de energia elétrica', + '2306': 'Aquisição de serviço de comunicação por estabelecimento de produtor rural', + '2350': 'AQUISIÇÕES DE SERVIÇOS DE TRANSPORTE', + '2351': 'Aquisição de serviço de transporte para execução de serviço da mesma natureza', + '2352': 'Aquisição de serviço de transporte por estabelecimento industrial', + '2353': 'Aquisição de serviço de transporte por estabelecimento comercial', + '2354': 'Aquisição de serviço de transporte por estabelecimento de prestador de serviço de comunicação', + '2355': 'Aquisição de serviço de transporte por estabelecimento de geradora ou de distribuidora de energia elétrica', + '2356': 'Aquisição de serviço de transporte por estabelecimento de produtor rural', + '2400': 'ENTRADAS DE MERCADORIAS SUJEITAS AO REGIME DE SUBSTITUIÇÃO TRIBUTÁRIA', + '2401': 'Compra para industrialização ou produção rural em operação com mercadoria sujeita ao regime de substituição tributária', + '2403': 'Compra para comercialização em operação com mercadoria sujeita ao regime de substituição tributária', + '2406': 'Compra de bem para o ativo imobilizado cuja mercadoria está sujeita ao regime de substituição tributária', + '2407': 'Compra de mercadoria para uso ou consumo cuja mercadoria está sujeita ao regime de substituição tributária', + '2408': 'Transferência para industrialização ou produção rural em operação com mercadoria sujeita ao regime de substituição tributária', + '2409': 'Transferência para comercialização em operação com mercadoria sujeita ao regime de substituição tributária', + '2410': 'Devolução de venda de produção do estabelecimento em operação com produto sujeito ao regime de substituição tributária', + '2411': 'Devolução de venda de mercadoria adquirida ou recebida de terceiros em operação com mercadoria sujeita ao regime de substituição tributária', + '2414': 'Retorno de produção do estabelecimento, remetida para venda fora do estabelecimento em operação com produto sujeito ao regime de substituição tributária', + '2415': 'Retorno de mercadoria adquirida ou recebida de terceiros, remetida para venda fora do estabelecimento em operação com mercadoria sujeita ao regime de substituição tributária', + '2500': 'ENTRADAS DE MERCADORIAS REMETIDAS PARA FORMAÇÃO DE LOTE OU COM FIM ESPECÍFICO DE EXPORTAÇÃO E EVENTUAIS DEVOLUÇÕES', + '2501': 'Entrada de mercadoria recebida com fim específico de exportação', + '2503': 'Entrada decorrente de devolução de produto remetido com fim específico de exportação, de produção do estabelecimento', + '2504': 'Entrada decorrente de devolução de mercadoria remetida com fim específico de exportação, adquirida ou recebida de terceiros', + '2505': 'Entrada decorrente de devolução de mercadorias remetidas para formação de lote de exportação, de produtos industrializados ou produzidos pelo próprio estabelecimento', + '2506': 'Entrada decorrente de devolução de mercadorias, adquiridas ou recebidas de terceiros, remetidas para formação de lote de exportação', + '2550': 'OPERAÇÕES COM BENS DE ATIVO IMOBILIZADO E MATERIAIS PARA USO OU CONSUMO', + '2551': 'Compra de bem para o ativo imobilizado', + '2552': 'Transferência de bem do ativo imobilizado', + '2553': 'Devolução de venda de bem do ativo imobilizado', + '2554': 'Retorno de bem do ativo imobilizado remetido para uso fora do estabelecimento', + '2555': 'Entrada de bem do ativo imobilizado de terceiro, remetido para uso no estabelecimento', + '2556': 'Compra de material para uso ou consumo', + '2557': 'Transferência de material para uso ou consumo', + '2600': 'CRÉDITOS E RESSARCIMENTOS DE ICMS', + '2603': 'Ressarcimento de ICMS retido por substituição tributária', + '2650': 'ENTRADAS DE COMBUSTÍVEIS, DERIVADOS OU NÃO DE PETRÓLEO E LUBRIFICANTES', + '2651': 'Compra de combustível ou lubrificante para industrialização subseqüente', + '2652': 'Compra de combustível ou lubrificante para comercialização', + '2653': 'Compra de combustível ou lubrificante por consumidor ou usuário final', + '2658': 'Transferência de combustível e lubrificante para industrialização', + '2659': 'Transferência de combustível e lubrificante para comercialização', + '2660': 'Devolução de venda de combustível ou lubrificante destinado à industrialização subseqüente', + '2661': 'Devolução de venda de combustível ou lubrificante destinado à comercialização', + '2662': 'Devolução de venda de combustível ou lubrificante destinado a consumidor ou usuário final', + '2663': 'Entrada de combustível ou lubrificante para armazenagem', + '2664': 'Retorno de combustível ou lubrificante remetido para armazenagem', + '2900': 'OUTRAS ENTRADAS DE MERCADORIAS OU AQUISIÇÕES DE SERVIÇOS', + '2901': 'Entrada para industrialização por encomenda', + '2902': 'Retorno de mercadoria remetida para industrialização por encomenda', + '2903': 'Entrada de mercadoria remetida para industrialização e não aplicada no referido processo', + '2904': 'Retorno de remessa para venda fora do estabelecimento', + '2905': 'Entrada de mercadoria recebida para depósito em depósito fechado ou armazém geral', + '2906': 'Retorno de mercadoria remetida para depósito fechado ou armazém geral', + '2907': 'Retorno simbólico de mercadoria remetida para depósito fechado ou armazém geral', + '2908': 'Entrada de bem por conta de contrato de comodato', + '2909': 'Retorno de bem remetido por conta de contrato de comodato', + '2910': 'Entrada de bonificação, doação ou brinde', + '2911': 'Entrada de amostra grátis', + '2912': 'Entrada de mercadoria ou bem recebido para demonstração ou mostruário.', + '2913': 'Retorno de mercadoria ou bem remetido para demonstração, mostruário ou treinamento.', + '2914': 'Retorno de mercadoria ou bem remetido para exposição ou feira', + '2915': 'Entrada de mercadoria ou bem recebido para conserto ou reparo', + '2916': 'Retorno de mercadoria ou bem remetido para conserto ou reparo', + '2917': 'Entrada de mercadoria recebida em consignação mercantil ou industrial', + '2918': 'Devolução de mercadoria remetida em consignação mercantil ou industrial', + '2919': 'Devolução simbólica de mercadoria vendida ou utilizada em processo industrial, remetida anteriormente em consignação mercantil ou industrial', + '2920': 'Entrada de vasilhame ou sacaria', + '2921': 'Retorno de vasilhame ou sacaria', + '2922': 'Lançamento efetuado a título de simples faturamento decorrente de compra para recebimento futuro', + '2923': 'Entrada de mercadoria recebida do vendedor remetente, em venda à ordem', + '2924': 'Entrada para industrialização por conta e ordem do adquirente da mercadoria, quando esta não transitar pelo estabelecimento do adquirente', + '2925': 'Retorno de mercadoria remetida para industrialização por conta e ordem do adquirente da mercadoria, quando esta não transitar pelo estabelecimento do adquirente', + '2931': 'Lançamento efetuado pelo tomador do serviço de transporte quando a responsabilidade de retenção do imposto for atribuída ao remetente ou alienante da mercadoria, pelo serviço de transporte realizado por transportador autônomo ou por transportador não inscrito na unidade da Federação onde iniciado o serviço.', + '2932': 'Aquisição de serviço de transporte iniciado em unidade da Federação diversa daquela onde inscrito o prestador.', + '2933': 'Aquisição de serviço tributado pelo ISSQN', + '2934': 'Entrada simbólica de mercadoria recebida para depósito fechado ou armazém geral', + '2949': 'Outra entrada de mercadoria ou prestação de serviço não especificado', + '3000': 'ENTRADAS OU AQUISIÇÕES DE SERVIÇOS DO EXTERIOR', + '3100': 'COMPRAS PARA INDUSTRIALIZAÇÃO, PRODUÇÃO RURAL, COMERCIALIZAÇÃO OU PRESTAÇÃO DE SERVIÇOS', + '3101': 'Compra para industrialização ou produção rural', + '3102': 'Compra para comercialização', + '3126': 'Compra para utilização na prestação de serviço sujeita ao ICMS', + '3127': 'Compra para industrialização sob o regime de "drawback"', + '3128': 'Compra para utilização na prestação de serviço sujeita ao ISSQN', + '3129': 'Compra para industrialização sob o Regime Aduaneiro Especial de Entreposto Industrial sob Controle Informatizado do Sistema Público de Escrituração Digital (Recof-Sped).', + '3200': 'DEVOLUÇÕES DE VENDAS DE PRODUÇÃO PRÓPRIA, DE TERCEIROS OU ANULAÇÕES DE VALORES', + '3201': 'Devolução de venda de produção do estabelecimento', + '3202': 'Devolução de venda de mercadoria adquirida ou recebida de terceiros', + '3205': 'Anulação de valor relativo à prestação de serviço de comunicação', + '3206': 'Anulação de valor relativo à prestação de serviço de transporte', + '3207': 'Anulação de valor relativo à venda de energia elétrica', + '3211': 'Devolução de venda de produção do estabelecimento sob o regime de "drawback"', + '3212': 'Devolução de venda no mercado externo de mercadoria industrializada sob o Regime Aduaneiro Especial de Entreposto Industrial sob Controle Informatizado do Sistema Público de Escrituração Digital (Recof-Sped).', + '3250': 'COMPRAS DE ENERGIA ELÉTRICA', + '3251': 'Compra de energia elétrica para distribuição ou comercialização', + '3300': 'AQUISIÇÕES DE SERVIÇOS DE COMUNICAÇÃO', + '3301': 'Aquisição de serviço de comunicação para execução de serviço da mesma natureza', + '3350': 'AQUISIÇÕES DE SERVIÇOS DE TRANSPORTE', + '3351': 'Aquisição de serviço de transporte para execução de serviço da mesma natureza', + '3352': 'Aquisição de serviço de transporte por estabelecimento industrial', + '3353': 'Aquisição de serviço de transporte por estabelecimento comercial', + '3354': 'Aquisição de serviço de transporte por estabelecimento de prestador de serviço de comunicação', + '3355': 'Aquisição de serviço de transporte por estabelecimento de geradora ou de distribuidora de energia elétrica', + '3356': 'Aquisição de serviço de transporte por estabelecimento de produtor rural', + '3500': 'ENTRADAS DE MERCADORIAS REMETIDAS COM FIM ESPECÍFICO DE EXPORTAÇÃO E EVENTUAIS DEVOLUÇÕES', + '3503': 'Devolução de mercadoria exportada que tenha sido recebida com fim específico de exportação', + '3550': 'OPERAÇÕES COM BENS DE ATIVO IMOBILIZADO E MATERIAIS PARA USO OU CONSUMO', + '3551': 'Compra de bem para o ativo imobilizado', + '3553': 'Devolução de venda de bem do ativo imobilizado', + '3556': 'Compra de material para uso ou consumo', + '3650': 'ENTRADAS DE COMBUSTÍVEIS, DERIVADOS OU NÃO DE PETRÓLEO E LUBRIFICANTES', + '3651': 'Compra de combustível ou lubrificante para industrialização subseqüente', + '3652': 'Compra de combustível ou lubrificante para comercialização', + '3653': 'Compra de combustível ou lubrificante por consumidor ou usuário final', + '3900': 'OUTRAS ENTRADAS DE MERCADORIAS OU AQUISIÇÕES DE SERVIÇOS', + '3930': 'Lançamento efetuado a título de entrada de bem sob amparo de regime especial aduaneiro de admissão temporária', + '3949': 'Outra entrada de mercadoria ou prestação de serviço não especificado', + '5000': 'SAÍDAS OU PRESTAÇÕES DE SERVIÇOS PARA O ESTADO', + '5100': 'VENDAS DE PRODUÇÃO PRÓPRIA OU DE TERCEIROS', + '5101': 'Venda de produção do estabelecimento', + '5102': 'Venda de mercadoria adquirida ou recebida de terceiros', + '5103': 'Venda de produção do estabelecimento, efetuada fora do estabelecimento', + '5104': 'Venda de mercadoria adquirida ou recebida de terceiros, efetuada fora do estabelecimento', + '5105': 'Venda de produção do estabelecimento que não deva por ele transitar', + '5106': 'Venda de mercadoria adquirida ou recebida de terceiros, que não deva por ele transitar', + '5109': 'Venda de produção do estabelecimento, destinada à Zona Franca de Manaus ou Áreas de Livre Comércio', + '5110': 'Venda de mercadoria adquirida ou recebida de terceiros, destinada à Zona Franca de Manaus ou Áreas de Livre Comércio', + '5111': 'Venda de produção do estabelecimento remetida anteriormente em consignação industrial', + '5112': 'Venda de mercadoria adquirida ou recebida de terceiros remetida anteriormente em consignação industrial', + '5113': 'Venda de produção do estabelecimento remetida anteriormente em consignação mercantil', + '5114': 'Venda de mercadoria adquirida ou recebida de terceiros remetida anteriormente em consignação mercantil', + '5115': 'Venda de mercadoria adquirida ou recebida de terceiros, recebida anteriormente em consignação mercantil', + '5116': 'Venda de produção do estabelecimento originada de encomenda para entrega futura', + '5117': 'Venda de mercadoria adquirida ou recebida de terceiros, originada de encomenda para entrega futura', + '5118': 'Venda de produção do estabelecimento entregue ao destinatário por conta e ordem do adquirente originário, em venda à ordem', + '5119': 'Venda de mercadoria adquirida ou recebida de terceiros entregue ao destinatário por conta e ordem do adquirente originário, em venda à ordem', + '5120': 'Venda de mercadoria adquirida ou recebida de terceiros entregue ao destinatário pelo vendedor remetente, em venda à ordem', + '5122': 'Venda de produção do estabelecimento remetida para industrialização, por conta e ordem do adquirente, sem transitar pelo estabelecimento do adquirente', + '5123': 'Venda de mercadoria adquirida ou recebida de terceiros remetida para industrialização, por conta e ordem do adquirente, sem transitar pelo estabelecimento do adquirente', + '5124': 'Industrialização efetuada para outra empresa', + '5125': 'Industrialização efetuada para outra empresa quando a mercadoria recebida para utilização no processo de industrialização não transitar pelo estabelecimento adquirente da mercadoria', + '5129': 'Venda de insumo importado e de mercadoria industrializada sob o amparo do Regime Aduaneiro Especial de Entreposto Industrial sob Controle Informatizado do Sistema Público de Escrituração Digital (Recof-Sped).', + '5131': 'Remessa de produção do estabelecimento, com previsão de posterior ajuste ou fixação de preço, de ato cooperativo.', + '5132': 'Fixação de preço de produção do estabelecimento, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço de ato cooperativo.', + '5150': 'TRANSFERÊNCIAS DE PRODUÇÃO PRÓPRIA OU DE TERCEIROS', + '5151': 'Transferência de produção do estabelecimento', + '5152': 'Transferência de mercadoria adquirida ou recebida de terceiros', + '5153': 'Transferência de energia elétrica', + '5155': 'Transferência de produção do estabelecimento, que não deva por ele transitar', + '5156': 'Transferência de mercadoria adquirida ou recebida de terceiros, que não deva por ele transitar', + '5159': 'Fornecimento de produção do estabelecimento de ato cooperativo', + '5160': 'Fornecimento de mercadoria adquirida ou recebida de terceiros de ato cooperativo', + '5200': 'DEVOLUÇÕES DE COMPRAS PARA INDUSTRIALIZAÇÃO, PRODUÇÃO RURAL, COMERCIALIZAÇÃO OU ANULAÇÕES DE VALORES', + '5201': 'Devolução de compra para industrialização ou produção rural', + '5202': 'Devolução de compra para comercialização', + '5205': 'Anulação de valor relativo a aquisição de serviço de comunicação', + '5206': 'Anulação de valor relativo a aquisição de serviço de transporte', + '5207': 'Anulação de valor relativo à compra de energia elétrica', + '5208': 'Devolução de mercadoria recebida em transferência para industrialização ou produção rural', + '5209': 'Devolução de mercadoria recebida em transferência para comercialização', + '5210': 'Devolução de compra para utilização na prestação de serviço', + '5213': 'Devolução de entrada de mercadoria com previsão de posterior ajuste ou fixação de preço, em ato cooperativo.', + '5214': 'Devolução de fixação de preço de produção do estabelecimento produtor, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço, de ato cooperativo, para comercialização.', + '5215': 'Devolução de fixação de preço de produção do estabelecimento produtor, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço, de ato cooperativo, para industrialização.', + '5250': 'VENDAS DE ENERGIA ELÉTRICA', + '5251': 'Venda de energia elétrica para distribuição ou comercialização', + '5252': 'Venda de energia elétrica para estabelecimento industrial', + '5253': 'Venda de energia elétrica para estabelecimento comercial', + '5254': 'Venda de energia elétrica para estabelecimento prestador de serviço de transporte', + '5255': 'Venda de energia elétrica para estabelecimento prestador de serviço de comunicação', + '5256': 'Venda de energia elétrica para estabelecimento de produtor rural', + '5257': 'Venda de energia elétrica para consumo por demanda contratada', + '5258': 'Venda de energia elétrica a não contribuinte', + '5300': 'PRESTAÇÕES DE SERVIÇOS DE COMUNICAÇÃO', + '5301': 'Prestação de serviço de comunicação para execução de serviço da mesma natureza', + '5302': 'Prestação de serviço de comunicação a estabelecimento industrial', + '5303': 'Prestação de serviço de comunicação a estabelecimento comercial', + '5304': 'Prestação de serviço de comunicação a estabelecimento de prestador de serviço de transporte', + '5305': 'Prestação de serviço de comunicação a estabelecimento de geradora ou de distribuidora de energia elétrica', + '5306': 'Prestação de serviço de comunicação a estabelecimento de produtor rural', + '5307': 'Prestação de serviço de comunicação a não contribuinte', + '5350': 'PRESTAÇÕES DE SERVIÇOS DE TRANSPORTE', + '5351': 'Prestação de serviço de transporte para execução de serviço da mesma natureza', + '5352': 'Prestação de serviço de transporte a estabelecimento industrial', + '5353': 'Prestação de serviço de transporte a estabelecimento comercial', + '5354': 'Prestação de serviço de transporte a estabelecimento de prestador de serviço de comunicação', + '5355': 'Prestação de serviço de transporte a estabelecimento de geradora ou de distribuidora de energia elétrica', + '5356': 'Prestação de serviço de transporte a estabelecimento de produtor rural', + '5357': 'Prestação de serviço de transporte a não contribuinte', + '5359': 'Prestação de serviço de transporte a contribuinte ou a não contribuinte quando a mercadoria transportada está dispensada de emissão de nota fiscal.', + '5360': 'Prestação de serviço de transporte a contribuinte substituto em relação ao serviço de transporte', + '5400': 'SAÍDAS DE MERCADORIAS SUJEITAS AO REGIME DE SUBSTITUIÇÃO TRIBUTÁRIA', + '5401': 'Venda de produção do estabelecimento em operação com produto sujeito ao regime de substituição tributária, na condição de contribuinte substituto', + '5402': 'Venda de produção do estabelecimento de produto sujeito ao regime de substituição tributária, em operação entre contribuintes substitutos do mesmo produto', + '5403': 'Venda de mercadoria adquirida ou recebida de terceiros em operação com mercadoria sujeita ao regime de substituição tributária, na condição de contribuinte substituto', + '5405': 'Venda de mercadoria adquirida ou recebida de terceiros em operação com mercadoria sujeita ao regime de substituição tributária, na condição de contribuinte substituído', + '5408': 'Transferência de produção do estabelecimento em operação com produto sujeito ao regime de substituição tributária', + '5409': 'Transferência de mercadoria adquirida ou recebida de terceiros em operação com mercadoria sujeita ao regime de substituição tributária', + '5410': 'Devolução de compra para industrialização ou produção rural em operação com mercadoria sujeita ao regime de substituição tributária', + '5411': 'Devolução de compra para comercialização em operação com mercadoria sujeita ao regime de substituição tributária', + '5412': 'Devolução de bem do ativo imobilizado, em operação com mercadoria sujeita ao regime de substituição tributária', + '5413': 'Devolução de mercadoria destinada ao uso ou consumo, em operação com mercadoria sujeita ao regime de substituição tributária', + '5414': 'Remessa de produção do estabelecimento para venda fora do estabelecimento em operação com produto sujeito ao regime de substituição tributária', + '5415': 'Remessa de mercadoria adquirida ou recebida de terceiros para venda fora do estabelecimento, em operação com mercadoria sujeita ao regime de substituição tributária', + '5450': 'SISTEMAS DE INTEGRAÇÃO', + '5451': 'Remessa de animal e de insumo para estabelecimento produtor', + '5500': 'REMESSAS PARA FORMAÇÃO DE LOTE E COM FIM ESPECÍFICO DE EXPORTAÇÃO E EVENTUAIS DEVOLUÇÕES', + '5501': 'Remessa de produção do estabelecimento, com fim específico de exportação', + '5502': 'Remessa de mercadoria adquirida ou recebida de terceiros, com fim específico de exportação', + '5503': 'Devolução de mercadoria recebida com fim específico de exportação', + '5504': 'Remessa de mercadorias para formação de lote de exportação, de produtos industrializados ou produzidos pelo próprio estabelecimento.', + '5505': 'Remessa de mercadorias, adquiridas ou recebidas de terceiros, para formação de lote de exportação', + '5550': 'OPERAÇÕES COM BENS DE ATIVO IMOBILIZADO E MATERIAIS PARA USO OU CONSUMO', + '5551': 'Venda de bem do ativo imobilizado', + '5552': 'Transferência de bem do ativo imobilizado', + '5553': 'Devolução de compra de bem para o ativo imobilizado', + '5554': 'Remessa de bem do ativo imobilizado para uso fora do estabelecimento', + '5555': 'Devolução de bem do ativo imobilizado de terceiro, recebido para uso no estabelecimento', + '5556': 'Devolução de compra de material de uso ou consumo', + '5557': 'Transferência de material de uso ou consumo', + '5600': 'CRÉDITOS E RESSARCIMENTOS DE ICMS', + '5601': 'Transferência de crédito de ICMS acumulado', + '5602': 'Transferência de saldo credor de ICMS para outro estabelecimento da mesma empresa, destinado à compensação de saldo devedor de ICMS', + '5603': 'Ressarcimento de ICMS retido por substituição tributária', + '5605': 'Transferência de saldo devedor de ICMS de outro estabelecimento da mesma empresa.', + '5606': 'Utilização de saldo credor de ICMS para extinção por compensação de débitos fiscais.', + '5650': 'SAÍDAS DE COMBUSTÍVEIS, DERIVADOS OU NÃO DE PETRÓLEO E LUBRIFICANTES', + '5651': 'Venda de combustível ou lubrificante de produção do estabelecimento destinado à industrialização subseqüente', + '5652': 'Venda de combustível ou lubrificante de produção do estabelecimento destinado à comercialização', + '5653': 'Venda de combustível ou lubrificante de produção do estabelecimento destinado a consumidor ou usuário final', + '5654': 'Venda de combustível ou lubrificante adquirido ou recebido de terceiros destinado à industrialização subseqüente', + '5655': 'Venda de combustível ou lubrificante adquirido ou recebido de terceiros destinado à comercialização', + '5656': 'Venda de combustível ou lubrificante adquirido ou recebido de terceiros destinado a consumidor ou usuário final', + '5657': 'Remessa de combustível ou lubrificante adquirido ou recebido de terceiros para venda fora do estabelecimento', + '5658': 'Transferência de combustível ou lubrificante de produção do estabelecimento', + '5659': 'Transferência de combustível ou lubrificante adquirido ou recebido de terceiro', + '5660': 'Devolução de compra de combustível ou lubrificante adquirido para industrialização subseqüente', + '5661': 'Devolução de compra de combustível ou lubrificante adquirido para comercialização', + '5662': 'Devolução de compra de combustível ou lubrificante adquirido por consumidor ou usuário final', + '5663': 'Remessa para armazenagem de combustível ou lubrificante', + '5664': 'Retorno de combustível ou lubrificante recebido para armazenagem', + '5665': 'Retorno simbólico de combustível ou lubrificante recebido para armazenagem', + '5666': 'Remessa por conta e ordem de terceiros de combustível ou lubrificante recebido para armazenagem', + '5667': 'Venda de combustível ou lubrificante a consumidor ou usuário final estabelecido em outra unidade da Federação', + '5900': 'OUTRAS SAÍDAS DE MERCADORIAS OU PRESTAÇÕES DE SERVIÇOS', + '5901': 'Remessa para industrialização por encomenda', + '5902': 'Retorno de mercadoria utilizada na industrialização por encomenda', + '5903': 'Retorno de mercadoria recebida para industrialização e não aplicada no referido processo', + '5904': 'Remessa para venda fora do estabelecimento', + '5905': 'Remessa para depósito fechado ou armazém geral', + '5906': 'Retorno de mercadoria depositada em depósito fechado ou armazém geral', + '5907': 'Retorno simbólico de mercadoria depositada em depósito fechado ou armazém geral', + '5908': 'Remessa de bem por conta de contrato de comodato', + '5909': 'Retorno de bem recebido por conta de contrato de comodato', + '5910': 'Remessa em bonificação, doação ou brinde', + '5911': 'Remessa de amostra grátis', + '5912': 'Remessa de mercadoria ou bem para demonstração, mostruário ou treinamento.', + '5913': 'Retorno de mercadoria ou bem recebido para demonstração ou mostruário.', + '5914': 'Remessa de mercadoria ou bem para exposição ou feira', + '5915': 'Remessa de mercadoria ou bem para conserto ou reparo', + '5916': 'Retorno de mercadoria ou bem recebido para conserto ou reparo', + '5917': 'Remessa de mercadoria em consignação mercantil ou industrial', + '5918': 'Devolução de mercadoria recebida em consignação mercantil ou industrial', + '5919': 'Devolução simbólica de mercadoria vendida ou utilizada em processo industrial, recebida anteriormente em consignação mercantil ou industrial', + '5920': 'Remessa de vasilhame ou sacaria', + '5921': 'Devolução de vasilhame ou sacaria', + '5922': 'Lançamento efetuado a título de simples faturamento decorrente de venda para entrega futura', + '5923': 'Remessa de mercadoria por conta e ordem de terceiros, em venda à ordem ou em operações com armazém geral ou depósito fechado.', + '5924': 'Remessa para industrialização por conta e ordem do adquirente da mercadoria, quando esta não transitar pelo estabelecimento do adquirente', + '5925': 'Retorno de mercadoria recebida para industrialização por conta e ordem do adquirente da mercadoria, quando aquela não transitar pelo estabelecimento do adquirente', + '5926': 'Lançamento efetuado a título de reclassificação de mercadoria decorrente de formação de kit ou de sua desagregação', + '5927': 'Lançamento efetuado a título de baixa de estoque decorrente de perda, roubo ou deterioração', + '5928': 'Lançamento efetuado a título de baixa de estoque decorrente do encerramento da atividade da empresa', + '5929': 'Lançamento efetuado em decorrência de emissão de documento fiscal relativo a operação ou prestação também registradaem equipamento Emissorde Cupom Fiscal - ECF', + '5931': 'Lançamento efetuado em decorrência da responsabilidade de retenção do imposto por substituição tributária, atribuída ao remetente ou alienante da mercadoria, pelo serviço de transporte realizado por transportador autônomo ou por transportador não inscrito na unidade da Federação onde iniciado o serviço', + '5932': 'Prestação de serviço de transporte iniciada em unidade da Federação diversa daquela onde inscrito o prestador', + '5933': 'Prestação de serviço tributado pelo ISSQN', + '5934': 'Remessa simbólica de mercadoria depositada em armazém geral ou depósito fechado', + '5949': 'Outra saída de mercadoria ou prestação de serviço não especificado', + '6000': 'SAÍDAS OU PRESTAÇÕES DE SERVIÇOS PARA OUTROS ESTADOS', + '6100': 'VENDAS DE PRODUÇÃO PRÓPRIA OU DE TERCEIROS', + '6101': 'Venda de produção do estabelecimento', + '6102': 'Venda de mercadoria adquirida ou recebida de terceiros', + '6103': 'Venda de produção do estabelecimento, efetuada fora do estabelecimento', + '6104': 'Venda de mercadoria adquirida ou recebida de terceiros, efetuada fora do estabelecimento', + '6105': 'Venda de produção do estabelecimento que não deva por ele transitar', + '6106': 'Venda de mercadoria adquirida ou recebida de terceiros, que não deva por ele transitar', + '6107': 'Venda de produção do estabelecimento, destinada a não contribuinte', + '6108': 'Venda de mercadoria adquirida ou recebida de terceiros, destinada a não contribuinte', + '6109': 'Venda de produção do estabelecimento, destinada à Zona Franca de Manaus ou Áreas de Livre Comércio', + '6110': 'Venda de mercadoria adquirida ou recebida de terceiros, destinada à Zona Franca de Manaus ou Áreas de Livre Comércio', + '6111': 'Venda de produção do estabelecimento remetida anteriormente em consignação industrial', + '6112': 'Venda de mercadoria adquirida ou recebida de Terceiros remetida anteriormente em consignação industrial', + '6113': 'Venda de produção do estabelecimento remetida anteriormente em consignação mercantil', + '6114': 'Venda de mercadoria adquirida ou recebida de terceiros remetida anteriormente em consignação mercantil', + '6115': 'Venda de mercadoria adquirida ou recebida de terceiros, recebida anteriormente em consignação mercantil', + '6116': 'Venda de produção do estabelecimento originada de encomenda para entrega futura', + '6117': 'Venda de mercadoria adquirida ou recebida de terceiros, originada de encomenda para entrega futura', + '6118': 'Venda de produção do estabelecimento entregue ao destinatário por conta e ordem do adquirente originário, em venda à ordem', + '6119': 'Venda de mercadoria adquirida ou recebida de terceiros entregue ao destinatário por conta e ordem do adquirente originário, em venda à ordem', + '6120': 'Venda de mercadoria adquirida ou recebida de terceiros entregue ao destinatário pelo vendedor remetente, em venda à ordem', + '6122': 'Venda de produção do estabelecimento remetida para industrialização, por conta e ordem do adquirente, sem transitar pelo estabelecimento do adquirente', + '6123': 'Venda de mercadoria adquirida ou recebida de terceiros remetida para industrialização, por conta e ordem do adquirente, sem transitar pelo estabelecimento do adquirente', + '6124': 'Industrialização efetuada para outra empresa', + '6125': 'Industrialização efetuada para outra empresa quando a mercadoria recebida para utilização no processo de industrialização não transitar pelo estabelecimento adquirente da mercadoria', + '6129': 'Venda de insumo importado e de mercadoria industrializada sob o amparo do Regime Aduaneiro Especial de Entreposto Industrial sob Controle Informatizado do Sistema Público de Escrituração Digital (Recof-Sped).', + '6131': 'Remessa de produção de estabelecimento, com previsão de posterior ajuste ou fixação de preço de ato cooperativo.', + '6132': 'Fixação de preço de produção do estabelecimento, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço ou fixação de preço de ato cooperativo.', + '6150': 'TRANSFERÊNCIAS DE PRODUÇÃO PRÓPRIA OU DE TERCEIROS', + '6151': 'Transferência de produção do estabelecimento', + '6152': 'Transferência de mercadoria adquirida ou recebida de terceiros', + '6153': 'Transferência de energia elétrica', + '6155': 'Transferência de produção do estabelecimento, que não deva por ele transitar', + '6156': 'Transferência de mercadoria adquirida ou recebida de terceiros, que não deva por ele transitar', + '6159': 'Fornecimento de produção do estabelecimento de ato cooperativo', + '6160': 'Fornecimento de mercadoria adquirida ou recebida de terceiros de ato cooperativo', + '6200': 'DEVOLUÇÕES DE COMPRAS PARA INDUSTRIALIZAÇÃO, PRODUÇÃO RURAL, COMERCIALIZAÇÃO OU ANULAÇÕES DE VALORES', + '6201': 'Devolução de compra para industrialização ou produção rural', + '6202': 'Devolução de compra para comercialização', + '6205': 'Anulação de valor relativo a aquisição de serviço de comunicação', + '6206': 'Anulação de valor relativo a aquisição de serviço de transporte', + '6207': 'Anulação de valor relativo à compra de energia elétrica', + '6208': 'Devolução de mercadoria recebida em transferência para industrialização ou produção rural', + '6209': 'Devolução de mercadoria recebida em transferência para comercialização', + '6210': 'Devolução de compra para utilização na prestação de serviço', + '6213': 'Devolução de entrada de mercadoria com previsão de posterior ajuste ou fixação de preço, em ato cooperativo.', + '6214': 'Devolução de fixação de preço de produção do estabelecimento produtor, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço, de ato cooperativo, para comercialização.', + '6215': 'Devolução de fixação de preço de produção do estabelecimento produtor, inclusive quando remetidas anteriormente com previsão de posterior ajuste ou fixação de preço, de ato cooperativo para industrialização.', + '6250': 'VENDAS DE ENERGIA ELÉTRICA', + '6251': 'Venda de energia elétrica para distribuição ou comercialização', + '6252': 'Venda de energia elétrica para estabelecimento industrial', + '6253': 'Venda de energia elétrica para estabelecimento comercial', + '6254': 'Venda de energia elétrica para estabelecimento prestador de serviço de transporte', + '6255': 'Venda de energia elétrica para estabelecimento prestador de serviço de comunicação', + '6256': 'Venda de energia elétrica para estabelecimento de produtor rural', + '6257': 'Venda de energia elétrica para consumo por demanda contratada', + '6258': 'Venda de energia elétrica a não contribuinte', + '6300': 'PRESTAÇÕES DE SERVIÇOS DE COMUNICAÇÃO', + '6301': 'Prestação de serviço de comunicação para execução de serviço da mesma natureza', + '6302': 'Prestação de serviço de comunicação a estabelecimento industrial', + '6303': 'Prestação de serviço de comunicação a estabelecimento comercial', + '6304': 'Prestação de serviço de comunicação a estabelecimento de prestador de serviço de transporte', + '6305': 'Prestação de serviço de comunicação a estabelecimento de geradora ou de distribuidora de energia elétrica', + '6306': 'Prestação de serviço de comunicação a estabelecimento de produtor rural', + '6307': 'Prestação de serviço de comunicação a não contribuinte', + '6350': 'PRESTAÇÕES DE SERVIÇOS DE TRANSPORTE', + '6351': 'Prestação de serviço de transporte para execução de serviço da mesma natureza', + '6352': 'Prestação de serviço de transporte a estabelecimento industrial', + '6353': 'Prestação de serviço de transporte a estabelecimento comercial', + '6354': 'Prestação de serviço de transporte a estabelecimento de prestador de serviço de comunicação', + '6355': 'Prestação de serviço de transporte a estabelecimento de geradora ou de distribuidora de energia elétrica', + '6356': 'Prestação de serviço de transporte a estabelecimento de produtor rural', + '6357': 'Prestação de serviço de transporte a não contribuinte', + '6359': 'Prestação de serviço de transporte a contribuinte ou a não contribuinte quando a mercadoria transportada está dispensada de emissão de nota fiscal.', + '6360': 'Prestação de serviço de transporte a contribuinte substituto em relação ao serviço de transporte.', + '6400': 'SAÍDAS DE MERCADORIAS SUJEITAS AO REGIME DE SUBSTITUIÇÃO TRIBUTÁRIA', + '6401': 'Venda de produção do estabelecimento em operação com produto sujeito ao regime de substituição tributária, na condição de contribuinte substituto', + '6402': 'Venda de produção do estabelecimento de produto sujeito ao regime de substituição tributária, em operação entre contribuintes substitutos do mesmo produto', + '6403': 'Venda de mercadoria adquirida ou recebida de terceiros em operação com mercadoria sujeita ao regime de substituição tributária, na condição de contribuinte substituto', + '6404': 'Venda de mercadoria sujeita ao regime de substituição tributária, cujo imposto já tenha sido retido anteriormente', + '6408': 'Transferência de produção do estabelecimento em operação com produto sujeito ao regime de substituição tributária', + '6409': 'Transferência de mercadoria adquirida ou recebida de terceiros em operação com mercadoria sujeita ao regime de substituição tributária', + '6410': 'Devolução de compra para industrialização ou produção rural em operação com mercadoria sujeita ao regime de substituição tributária', + '6411': 'Devolução de compra para comercialização em operação com mercadoria sujeita ao regime de substituição tributária', + '6412': 'Devolução de bem do ativo imobilizado, em operação com mercadoria sujeita ao regime de substituição tributária', + '6413': 'Devolução de mercadoria destinada ao uso ou consumo, em operação com mercadoria sujeita ao regime de substituição tributária', + '6414': 'Remessa de produção do estabelecimento para venda fora do estabelecimento em operação com produto sujeito ao regime de substituição tributária', + '6415': 'Remessa de mercadoria adquirida ou recebida de terceiros para venda fora do estabelecimento, em operação com mercadoria sujeita ao regime de substituição tributária', + '6500': 'REMESSAS PARA FORMAÇÃO DE LOTE E COM FIM ESPECÍFICO DE EXPORTAÇÃO E EVENTUAIS DEVOLUÇÕES', + '6501': 'Remessa de produção do estabelecimento, com fim específico de exportação', + '6502': 'Remessa de mercadoria adquirida ou recebida de terceiros, com fim específico de exportação', + '6503': 'Devolução de mercadoria recebida com fim específico de exportação', + '6504': 'Remessa de mercadorias para formação de lote de exportação, de produtos industrializados ou produzidos pelo próprio estabelecimento.', + '6505': 'Remessa de mercadorias, adquiridas ou recebidas de terceiros, para formação de lote de exportação', + '6550': 'OPERAÇÕES COM BENS DE ATIVO IMOBILIZADO E MATERIAIS PARA USO OU CONSUMO', + '6551': 'Venda de bem do ativo imobilizado', + '6552': 'Transferência de bem do ativo imobilizado', + '6553': 'Devolução de compra de bem para o ativo imobilizado', + '6554': 'Remessa de bem do ativo imobilizado para uso fora do estabelecimento', + '6555': 'Devolução de bem do ativo imobilizado de terceiro, recebido para uso no estabelecimento', + '6556': 'Devolução de compra de material de uso ou consumo', + '6557': 'Transferência de material de uso ou consumo', + '6600': 'CRÉDITOS E RESSARCIMENTOS DE ICMS', + '6603': 'Ressarcimento de ICMS retido por substituição tributária', + '6650': 'SAÍDAS DE COMBUSTÍVEIS, DERIVADOS OU NÃO DE PETRÓLEO E LUBRIFICANTES', + '6651': 'Venda de combustível ou lubrificante de produção do estabelecimento destinado à industrialização subseqüente', + '6652': 'Venda de combustível ou lubrificante de produção do estabelecimento destinado à comercialização', + '6653': 'Venda de combustível ou lubrificante de produção do estabelecimento destinado a consumidor ou usuário final', + '6654': 'Venda de combustível ou lubrificante adquirido ou recebido de terceiros destinado à industrialização subseqüente', + '6655': 'Venda de combustível ou lubrificante adquirido ou recebido de terceiros destinado à comercialização', + '6656': 'Venda de combustível ou lubrificante adquirido ou recebido de terceiros destinado a consumidor ou usuário final', + '6657': 'Remessa de combustível ou lubrificante adquirido ou recebido de terceiros para venda fora do estabelecimento', + '6658': 'Transferência de combustível ou lubrificante de produção do estabelecimento', + '6659': 'Transferência de combustível ou lubrificante adquirido ou recebido de terceiro', + '6660': 'Devolução de compra de combustível ou lubrificante adquirido para industrialização subseqüente', + '6661': 'Devolução de compra de combustível ou lubrificante adquirido para comercialização', + '6662': 'Devolução de compra de combustível ou lubrificante adquirido por consumidor ou usuário final', + '6663': 'Remessa para armazenagem de combustível ou lubrificante', + '6664': 'Retorno de combustível ou lubrificante recebido para armazenagem', + '6665': 'Retorno simbólico de combustível ou lubrificante recebido para armazenagem', + '6666': 'Remessa por conta e ordem de terceiros de combustível ou lubrificante recebido para armazenagem', + '6667': 'Venda de combustível ou lubrificante a consumidor ou usuário final estabelecido em outra unidade da Federação diferente da que ocorrer o consumo', + '6900': 'OUTRAS SAÍDAS DE MERCADORIAS OU PRESTAÇÕES DE SERVIÇOS', + '6901': 'Remessa para industrialização por encomenda', + '6902': 'Retorno de mercadoria utilizada na industrialização por encomenda', + '6903': 'Retorno de mercadoria recebida para industrialização e não aplicada no referido processo', + '6904': 'Remessa para venda fora do estabelecimento', + '6905': 'Remessa para depósito fechado ou armazém geral', + '6906': 'Retorno de mercadoria depositada em depósito fechado ou armazém geral', + '6907': 'Retorno simbólico de mercadoria depositada em depósito fechado ou armazém geral', + '6908': 'Remessa de bem por conta de contrato de comodato', + '6909': 'Retorno de bem recebido por conta de contrato de comodato', + '6910': 'Remessa em bonificação, doação ou brinde', + '6911': 'Remessa de amostra grátis', + '6912': 'Remessa de mercadoria ou bem para demonstração, mostruário ou treinamento.', + '6913': 'Retorno de mercadoria ou bem recebido para demonstração ou mostruário.', + '6914': 'Remessa de mercadoria ou bem para exposição ou feira', + '6915': 'Remessa de mercadoria ou bem para conserto ou reparo', + '6916': 'Retorno de mercadoria ou bem recebido para conserto ou reparo', + '6917': 'Remessa de mercadoria em consignação mercantil ou industrial', + '6918': 'Devolução de mercadoria recebida em consignação mercantil ou industrial', + '6919': 'Devolução simbólica de mercadoria vendida ou utilizada em processo industrial, recebida anteriormente em consignação mercantil ou industrial', + '6920': 'Remessa de vasilhame ou sacaria', + '6921': 'Devolução de vasilhame ou sacaria', + '6922': 'Lançamento efetuado a título de simples faturamento decorrente de venda para entrega futura', + '6923': 'Remessa de mercadoria por conta e ordem de terceiros, em venda à ordem ou em operações com armazém geral ou depósito fechado', + '6924': 'Remessa para industrialização por conta e ordem do adquirente da mercadoria, quando esta não transitar pelo estabelecimento do adquirente', + '6925': 'Retorno de mercadoria recebida para industrialização por conta e ordem do adquirente da mercadoria, quando aquela não transitar pelo estabelecimento do adquirente', + '6929': 'Lançamento efetuado em decorrência de emissão de documento fiscal relativo a operação ou prestação também registradaem equipamento Emissorde Cupom Fiscal - ECF', + '6931': 'Lançamento efetuado em decorrência da responsabilidade de retenção do imposto por substituição tributária, atribuída ao remetente ou alienante da mercadoria, pelo serviço de transporte realizado por transportador autônomo ou por transportador não inscrito na unidade da Federação onde iniciado o serviço', + '6932': 'Prestação de serviço de transporte iniciada em unidade da Federação diversa daquela onde inscrito o prestador', + '6933': 'Prestação de serviço tributado pelo ISSQN', + '6934': 'Remessa simbólica de mercadoria depositada em armazém geral ou depósito fechado', + '6949': 'Outra saída de mercadoria ou prestação de serviço não especificado', + '7000': 'SAÍDAS OU PRESTAÇÕES DE SERVIÇOS PARA O EXTERIOR', + '7100': 'VENDAS DE PRODUÇÃO PRÓPRIA OU DE TERCEIROS', + '7101': 'Venda de produção do estabelecimento', + '7102': 'Venda de mercadoria adquirida ou recebida de terceiros', + '7105': 'Venda de produção do estabelecimento, que não deva por ele transitar', + '7106': 'Venda de mercadoria adquirida ou recebida de terceiros, que não deva por ele transitar', + '7127': 'Venda de produção do estabelecimento sob o regime de "drawback"', + '7129': 'Venda de produção do estabelecimento ao mercado externo de mercadoria industrializada sob o amparo do Regime Aduaneiro Especial de Entreposto Industrial sob Controle Informatizado do Sistema Público de Escrituração Digital (Recof-Sped).', + '7200': 'DEVOLUÇÕES DE COMPRAS PARA INDUSTRIALIZAÇÃO, PRODUÇÃO RURAL, COMERCIALIZAÇÃO OU ANULAÇÕES DE VALORES', + '7201': 'Devolução de compra para industrialização ou produção rural', + '7202': 'Devolução de compra para comercialização', + '7205': 'Anulação de valor relativo à aquisição de serviço de comunicação', + '7206': 'Anulação de valor relativo a aquisição de serviço de transporte', + '7207': 'Anulação de valor relativo à compra de energia elétrica', + '7210': 'Devolução de compra para utilização na prestação de serviço', + '7211': 'Devolução de compras para industrialização sob o regime de drawback', + '7212': 'Devolução de compras para industrialização sob o regime de Regime Aduaneiro Especial de Entreposto Industrial sob Controle Informatizado do Sistema Público de Escrituração Digital (Recof-Sped).', + '7250': 'VENDAS DE ENERGIA ELÉTRICA', + '7251': 'Venda de energia elétrica para o exterior', + '7300': 'PRESTAÇÕES DE SERVIÇOS DE COMUNICAÇÃO', + '7301': 'Prestação de serviço de comunicação para execução de serviço da mesma natureza', + '7350': 'PRESTAÇÕES DE SERVIÇO DE TRANSPORTE', + '7358': 'Prestação de serviço de transporte', + '7500': 'EXPORTAÇÃO DE MERCADORIAS RECEBIDAS COM FIM ESPECÍFICO DE EXPORTAÇÃO', + '7501': 'Exportação de mercadorias recebidas com fim específico de exportação', + '7504': 'Exportação de mercadoria que foi objeto de formação de lote de exportação', + '7550': 'OPERAÇÕES COM BENS DE ATIVO IMOBILIZADO E MATERIAIS PARA USO OU CONSUMO', + '7551': 'Venda de bem do ativo imobilizado', + '7553': 'Devolução de compra de bem para o ativo imobilizado', + '7556': 'Devolução de compra de material de uso ou consumo', + '7650': 'SAÍDAS DE COMBUSTÍVEIS, DERIVADOS OU NÃO DE PETRÓLEO E LUBRIFICANTES', + '7651': 'Venda de combustível ou lubrificante de produção do estabelecimento', + '7654': 'Venda de combustível ou lubrificante adquirido ou recebido de terceiros', + '7667': 'Venda de combustível ou lubrificante a consumidor ou usuário final.', + '7900': 'OUTRAS SAÍDAS DE MERCADORIAS OU PRESTAÇÕES DE SERVIÇOS', + '7930': 'Lançamento efetuado a título de devolução de bem cuja entrada tenha ocorrido sob amparo de regime especial aduaneiro de admissão temporária', + '7949': 'Outra saída de mercadoria ou prestação de serviço não especificado', + } \ No newline at end of file From ea12f6e305db4137d697db41f23fc70268e390bc Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:10:07 -0300 Subject: [PATCH 17/52] =?UTF-8?q?[fix]=20corrigido=20d=C3=ADgito=20verific?= =?UTF-8?q?ador=20do=20CPF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/pis_cofins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pis_cofins.py b/test/pis_cofins.py index 250a162..7617c62 100644 --- a/test/pis_cofins.py +++ b/test/pis_cofins.py @@ -60,7 +60,7 @@ def test_read_registro(self): contabilista = Registro0100() contabilista.NOME = 'Daniel Sadamo' - contabilista.CPF = '12334532212' + contabilista.CPF = '12334532207' contabilista.CRC = '532212' contabilista.END = 'Rua dos ferroviario' contabilista.NUM = '123' From 49d0ad011609725b61c2ec809b50f3d26327e904 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Fri, 28 Feb 2020 23:52:28 -0300 Subject: [PATCH 18/52] =?UTF-8?q?instru=C3=A7=C3=B5es=20detalhadas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_relatorios.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 2d4a42e..4cf6bf7 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -1,19 +1,30 @@ #!/usr/bin/env python3 Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '14 de Fevereiro de 2020 (início: 29 de Janeiro de 2020)' +Data = '28 de Fevereiro de 2020 (início: 29 de Janeiro de 2020)' # Instruções (no Linux): - # Digite em seu web brawser o endereço abaixo: -# https://github.com/claudiofsr/python-sped -# Clique em 'Clone or download'. + +# Escolha a opção A ou B: +# A: https://github.com/claudiofsr +# Selecione o projeto 'python-sped'. +# Em seguida selecione o Branch 'relatorios'. +# B: https://github.com/claudiofsr/python-sped/tree/relatorios + +# Execute os passos 1 ou 2: +# 1. Na linha de comando execute: +# > git clone -b relatorios git@github.com:claudiofsr/python-sped.git +# Em seguida, vá ao diretório python-sped: +# > cd python-sped +# 2. Em 'Clone ou download' clique em 'Download ZIP': # Em seguida, descompacte o arquivo copiado: -# > unzip python-sped-11.0.zip -# > cd python-sped-11.0 -# Para instalar o módulo do sped em seu sistema execute, como superusuário: +# > unzip python-sped-relatorios.zip +# > cd python-sped-relatorios + +# Para instalar o módulo do SPED em seu sistema execute, como superusuário: # python setup.py install -# Copie o arquivo 'efd_relatorios.py' de python-sped-11.0/relatorios +# Copie o arquivo 'efd_relatorios.py' de python-sped/relatorios # para o diretório que contenha os arquivos de EFD Contribuições. # Em seguida, execute no terminal o camando: # > python efd_relatorios.py From 4163286ec14b319cfc134f50c69fcc14b9705d64 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sat, 29 Feb 2020 12:09:56 -0300 Subject: [PATCH 19/52] =?UTF-8?q?registrar=20efd=5Frelatorios=20como=20exe?= =?UTF-8?q?cut=C3=A1vel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.py | 9 ++++++-- sped/campos.py | 2 +- sped/relatorios/efd_info.py | 2 +- sped/relatorios/efd_relatorios.py | 36 +++++++++++++++---------------- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/setup.py b/setup.py index 79a2e69..e318d89 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,6 @@ from setuptools.command.test import test as test_command from sped import __version__ - class PyTest(test_command): user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")] @@ -25,7 +24,6 @@ def run_tests(self): errno = pytest.main(self.pytest_args) sys.exit(errno) - setup( name='python-sped', packages=find_packages(exclude=['contrib', 'docs', 'test*']), @@ -60,4 +58,11 @@ def run_tests(self): ] }, cmdclass={'test': PyTest}, + + # https://stackoverflow.com/questions/4840182/setup-py-and-adding-file-to-bin + # scripts=['sped/relatorios/efd_relatorios'] + + entry_points = { + 'console_scripts': ['efd_relatorios=sped.relatorios.efd_relatorios:main'] + }, ) diff --git a/sped/campos.py b/sped/campos.py index aae7308..3c64bc6 100644 --- a/sped/campos.py +++ b/sped/campos.py @@ -383,4 +383,4 @@ class CampoNCM(Campo): def formatar(ncm): if len(ncm) == 8: ncm = "%s.%s.%s" % (ncm[0:4],ncm[4:6],ncm[6:8]) - return ncm \ No newline at end of file + return ncm diff --git a/sped/relatorios/efd_info.py b/sped/relatorios/efd_info.py index 50235b1..c4699b9 100644 --- a/sped/relatorios/efd_info.py +++ b/sped/relatorios/efd_info.py @@ -339,7 +339,7 @@ def imprimir_informacoes(self): self.info_de_abertura = self.obter_info_de_abertura(self.objeto_sped) - filename, _ = os.path.splitext(self.file_path) + filename = os.path.splitext(self.file_path)[0] # ('./efd_info', '.py') arquivo_csv = filename + '.csv' arquivo_excel = filename + '.xlsx' diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 4cf6bf7..44ee5c8 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 +# -*- coding: utf-8 -*- Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '28 de Fevereiro de 2020 (início: 29 de Janeiro de 2020)' +Data = '29 de Fevereiro de 2020 (início: 29 de Janeiro de 2020)' # Instruções (no Linux): # Digite em seu web brawser o endereço abaixo: @@ -23,11 +24,10 @@ # > cd python-sped-relatorios # Para instalar o módulo do SPED em seu sistema execute, como superusuário: -# python setup.py install -# Copie o arquivo 'efd_relatorios.py' de python-sped/relatorios -# para o diretório que contenha os arquivos de EFD Contribuições. -# Em seguida, execute no terminal o camando: -# > python efd_relatorios.py +# > python setup.py install +# Em um diretório que contenha arquivos de EFD Contribuições, +# execute no terminal o camando: +# > efd_relatorios import sys, os from time import time, sleep @@ -42,7 +42,7 @@ print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) exit() -if __name__ == '__main__': +def main(): print(f'\nPython Sped - versão: {__version__}\n') @@ -76,18 +76,14 @@ elif len(arquivos_sped_efd) == 1: indice_do_arquivo = 0 else: - dir_path_exemplo = '/home/claudio/Documentos/' - print(f"A lista de arquivos de SPED EFD é obtida a partir de:\n") - print(f"\tlista_de_arquivos = ReadFiles(root_path = dir_path, extension = extensao).\n") - print(f"tal que:\n") - print(f"\tdir_path = '{dir_path}' e extensao = '{extensao}'.\n") - print(f"Nenhum arquivo de SPED EFD foi encontrado no diretório dir_path definido acima.") - print(f"Se as EFDs estão localizadas, por exemplo, no diretório '{dir_path_exemplo}',") - print(f"então altere a variável 'dir_path' para o diretório que contenha as EFDs:") - print(f"\n\tdir_path = '{dir_path_exemplo}'\n") - print(f"Outra alternativa é copiar este arquivo '{__file__}' para o diretório que contenha as EFDs.") - print(f"Em seguida, executar no terminal:\n") - print(f"\t python {__file__} \n") + # https://stackoverflow.com/questions/8384737/extract-file-name-from-path-no-matter-what-the-os-path-format + basename = os.path.basename(__file__) # 'efd_relatorios' + file_ext = os.path.splitext(__file__)[-1] # ('./efd_relatorios', '.py') + executavel = basename.replace(file_ext, '') + + print(f"Execute este programa no diretório que contenha os arquivos SPED EFD.") + print(f"Na linha de comando, digite:\n") + print(f"\t{executavel}\n") exit() # arquivo SPED EFD @@ -109,3 +105,5 @@ print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)} \n') +if __name__ == '__main__': + main() From 78c7513ccf711864d76aff4439125004d0e8fc7d Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:13:10 -0300 Subject: [PATCH 20/52] =?UTF-8?q?adicionar=20efd=5Frelatorios=20como=20exe?= =?UTF-8?q?cut=C3=A1vel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e318d89..860a07c 100644 --- a/setup.py +++ b/setup.py @@ -60,7 +60,7 @@ def run_tests(self): cmdclass={'test': PyTest}, # https://stackoverflow.com/questions/4840182/setup-py-and-adding-file-to-bin - # scripts=['sped/relatorios/efd_relatorios'] + # scripts=['sped/relatorios/efd_relatorios'], entry_points = { 'console_scripts': ['efd_relatorios=sped.relatorios.efd_relatorios:main'] From 29256cf33f753f3cba3a22867a266c616176349e Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:15:06 -0300 Subject: [PATCH 21/52] converter arquivo de formato csv para excel xlsx --- sped/relatorios/convert_csv_to_xlsx.py | 98 ++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 sped/relatorios/convert_csv_to_xlsx.py diff --git a/sped/relatorios/convert_csv_to_xlsx.py b/sped/relatorios/convert_csv_to_xlsx.py new file mode 100644 index 0000000..2ed1af6 --- /dev/null +++ b/sped/relatorios/convert_csv_to_xlsx.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- + +Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' +Data = '01 de Março de 2020 (início: 10 de Janeiro de 2020)' + +import sys, csv +import xlsxwriter # pip install xlsxwriter +from sped.relatorios.switcher import My_Switch +from sped.relatorios.print_csv_file import SPED_EFD_Info + +# Versão mínima exigida: python 3.6.0 +python_version = sys.version_info +if python_version < (3,6,0): + print('versão mínima exigida do python é 3.6.0') + print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) + exit() + +# Python OOP: Atributos e Métodos (def, funções) +class CSV_to_Excel: + """ + converter arquivo de formato .csv para .xlsx do excel + """ + + # initialize the attributes of the class + + def __init__(self, arquivo_csv, arquivo_excel, verbose=False): + self.imput_csv = arquivo_csv + self.output_excel = arquivo_excel + self.verbose = verbose + + @property + def convert_csv_to_xlsx(self): + + # Create an new Excel file and add a worksheet. + workbook = xlsxwriter.Workbook(self.output_excel) + worksheet = workbook.add_worksheet('Itens de Docs Fiscais') + workbook.set_properties({'comments': 'Created with Python and XlsxWriter'}) + + # definindo a altura da primeira coluna, row_index == 0 + worksheet.set_row(0, 30) + + # Freeze pane on the top row. + worksheet.freeze_panes(1, 0) + + # Set up some formatting + header_format = workbook.add_format({ + 'align':'center', 'valign':'vcenter', + 'bg_color':'#C5D9F1', 'text_wrap':True, + 'font_size':10}) + + select_value = My_Switch(SPED_EFD_Info.registros_totais,verbose=self.verbose) + select_value.formatar_valores_das_colunas() + myValue = select_value.dicionario + + select_format = My_Switch(SPED_EFD_Info.registros_totais,verbose=self.verbose) + select_format.formatar_colunas_do_arquivo_excel(workbook) + myFormat = select_format.dicionario + + # First we find the length of the header column + largura_max = [len(c) for c in SPED_EFD_Info.colunas_selecionadas] + + with open(self.imput_csv, 'r', encoding='utf-8', errors='ignore') as file: + + reader = csv.reader(file, delimiter=';') + for row_index, row in enumerate(reader): + + # nomes das colunas + if row_index == 0: + worksheet.write_row(row_index, 0, tuple(SPED_EFD_Info.colunas_selecionadas), header_format) + continue + + for column_index, cell in enumerate(row): + + # reter largura máxima + if len(cell) > largura_max[column_index]: + largura_max[column_index] = len(cell) + + column_name = SPED_EFD_Info.colunas_selecionadas[column_index] + + if len(cell) > 0: + worksheet.write(row_index, column_index, myValue[column_name](cell), myFormat[column_name]) + else: + # Write cell with row/column notation. + worksheet.write(row_index, column_index, cell) + + # Ajustar largura das colunas com os valores máximos + largura_min = 4 + for i, width in enumerate(largura_max): + if width > 120: # largura máxima + width = 120 + worksheet.set_column(i, i, width + largura_min) + + # Set the autofilter( $first_row, $first_col, $last_row, $last_col ) + worksheet.autofilter(0, 0, 0, len(largura_max) - 1) + + workbook.close() + + print(f"Gerado arquivo Excel .xlsx: '{self.output_excel}'.") From d10c9b29332344a114b78880b215e1391315b27d Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:18:11 -0300 Subject: [PATCH 22/52] =?UTF-8?q?imprime=20relat=C3=B3rios=20de=20SPED=20E?= =?UTF-8?q?FD=20em=20Excel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_relatorios.py | 40 ++++++++++++++++++------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 44ee5c8..cace835 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '29 de Fevereiro de 2020 (início: 29 de Janeiro de 2020)' +Data = '01 de Março de 2020 (início: 29 de Janeiro de 2020)' # Instruções (no Linux): # Digite em seu web brawser o endereço abaixo: @@ -32,8 +32,9 @@ import sys, os from time import time, sleep from sped import __version__ -from sped.relatorios.efd_read_dir import ReadFiles, Total_Execution_Time -from sped.relatorios.efd_info import SPED_EFD_Info +from sped.relatorios.find_efd_files import ReadFiles, Total_Execution_Time +from sped.relatorios.print_csv_file import SPED_EFD_Info +from sped.relatorios.convert_csv_to_xlsx import CSV_to_Excel # Versão mínima exigida: python 3.6.0 python_version = sys.version_info @@ -44,7 +45,7 @@ def main(): - print(f'\nPython Sped - versão: {__version__}\n') + print(f'\n\tPython Sped - versão: {__version__}\n') dir_path = os.getcwd() # CurrentDirectory extensao = 'txt' @@ -76,34 +77,39 @@ def main(): elif len(arquivos_sped_efd) == 1: indice_do_arquivo = 0 else: - # https://stackoverflow.com/questions/8384737/extract-file-name-from-path-no-matter-what-the-os-path-format - basename = os.path.basename(__file__) # 'efd_relatorios' - file_ext = os.path.splitext(__file__)[-1] # ('./efd_relatorios', '.py') - executavel = basename.replace(file_ext, '') - - print(f"Execute este programa no diretório que contenha os arquivos SPED EFD.") - print(f"Na linha de comando, digite:\n") - print(f"\t{executavel}\n") + print(f"\tDiretório atual: '{dir_path}'.") + print(f"\tNão foi encontrado arquivos SPED EFD neste diretório.\n") exit() # arquivo SPED EFD file_path = arquivos_sped_efd[indice_do_arquivo] tipo_da_efd = lista_de_arquivos.informations[file_path]['tipo'] codificacao = lista_de_arquivos.informations[file_path]['codificação'] + + filename = os.path.splitext(file_path)[0] # ('./efd_info', '.py') + arquivo_csv = filename + '.csv' + arquivo_excel = filename + '.xlsx' - print(f"\nFoi selecionado o arquivo {indice_do_arquivo + 1}: '{file_path}'\n") - input("Tecle Enter para gerar arquivo .csv com informações da EFD ") + print(f"\nSelecionado o arquivo {indice_do_arquivo + 1}: '{file_path}'.\n") + input("Tecle Enter para gerar arquivo Excel .xlsx com informações da SPED EFD.") print() start = time() - efd = SPED_EFD_Info(file_path, encoding=codificacao, efd_tipo = tipo_da_efd, verbose=False) + csv_file = SPED_EFD_Info(file_path, encoding=codificacao, efd_tipo = tipo_da_efd, verbose=False) - efd.imprimir_informacoes + csv_file.imprimir_arquivo_csv + + excel_file = CSV_to_Excel(arquivo_csv, arquivo_excel, verbose=False) + + excel_file.convert_csv_to_xlsx + + if os.path.exists(arquivo_csv): + os.remove(arquivo_csv) end = time() - print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)} \n') + print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)}\n') if __name__ == '__main__': main() From f957baef513be561beda6cfc45d89e8bf88fb9f6 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:21:46 -0300 Subject: [PATCH 23/52] =?UTF-8?q?substitui=20v=C3=A1rios=20if/then/else=20?= =?UTF-8?q?por=20dicionario?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/switcher.py | 219 ++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 sped/relatorios/switcher.py diff --git a/sped/relatorios/switcher.py b/sped/relatorios/switcher.py new file mode 100644 index 0000000..37528ee --- /dev/null +++ b/sped/relatorios/switcher.py @@ -0,0 +1,219 @@ +# -*- coding: utf-8 -*- + +Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' +Data = '01 de Março de 2020 (início: 10 de Janeiro de 2020)' + +import sys, re +from datetime import datetime +from sped.campos import (CampoData, CampoCNPJ, CampoCPF, CampoNCM, + CampoCPFouCNPJ, CampoChaveEletronica) + +# Versão mínima exigida: python 3.6.0 +python_version = sys.version_info +if python_version < (3,6,0): + print('versão mínima exigida do python é 3.6.0') + print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) + exit() + +class My_Switch: + """ + Definir, apenas uma vez, um dicionário ao invés de utilizar vários 'if/then/else' a cada + execução de formatar_valor(): + dict[key] = funtion_key(value) + Ao escolher uma chave, o dicionário aplica uma função (que depende da chave) sobre o valor + Esta construção possui Ordem O(1). + Caso fossem utilizados vários if/then/else (ou switch) a ordem seria O(N), que é mais lento! + """ + + @staticmethod + def funcao_identidade(chave): + return chave + + @staticmethod + def formatar_linhas(numero): + return f'{int(numero):09d}' + + @staticmethod + def formatar_mes(mes_num): + try: + mes_num = f'{int(mes_num):02d}' + return f'{EFD_Tabelas.tabela_mes_nominal[mes_num]}' + except: + return mes_num + + @staticmethod + def formatar_registro(registro): + try: + return f'{registro} - {EFD_Tabelas.tabela_info_do_registro[registro]}' + except: + reg = registro[0] + return f'{registro} - {EFD_Tabelas.tabela_info_do_registro[reg]}' + + @staticmethod + def formatar_cfop(cfop): + try: + cfop = f'{int(cfop):04d}' + return f'{cfop} - {EFD_Tabelas.tabela_cfop_descricao[cfop]}' + except: + return cfop + + @staticmethod + def formatar_cst_contrib(codigo_cst): + try: + codigo_cst = f'{int(codigo_cst):02d}' + return f'{codigo_cst} - {EFD_Tabelas.tabela_cst_contrib[codigo_cst]}' + except: + return codigo_cst + + @staticmethod + def formatar_cst_icms(codigo_cst): + try: + codigo_cst = f'{int(codigo_cst):03d}' + return f'{codigo_cst} - {EFD_Tabelas.tabela_cst_icms[codigo_cst]}' + except: + return codigo_cst + + @staticmethod + def formatar_nbc(natureza_bc): + try: + natureza_bc = f'{int(natureza_bc):02d}' + return f'{natureza_bc} - {EFD_Tabelas.tabela_bc_do_credito[natureza_bc]}' + except: + return natureza_bc + + @staticmethod + def formatar_tipo(tipo_do_item): + try: + tipo_do_item = f'{int(tipo_do_item):02d}' + return f'{tipo_do_item} - {EFD_Tabelas.tabela_tipo_do_item[tipo_do_item]}' + except: + return tipo_do_item + + @staticmethod + def formatar_mod(doc_fiscal): + try: + return f'{doc_fiscal} - {EFD_Tabelas.tabela_modelos_documentos_fiscais[doc_fiscal]}' + except: + return doc_fiscal + + @staticmethod + def formatar_valores_reais(valor): + try: + return float(valor) + except: + valor = valor.replace( '.', '' ) # 4.218.239,19 --> 4218239,19 + valor = valor.replace( ',', '.' ) # 4218239,19 --> 4218239.19 + return float(valor) + + @staticmethod + def formatar_datas(data): + date_time = datetime.strptime(data, "%d/%m/%Y") # dd/mm/aaaa + return date_time + + # initialize the attributes of the class + + def __init__(self, lista_de_colunas, verbose=False): + self.lista_de_colunas = lista_de_colunas + self.verbose = verbose + self.dicionario = {} + + def formatar_colunas_do_arquivo_csv(self): + + for nome_da_coluna in self.lista_de_colunas: + + match_linha = re.search(r'^Linhas', nome_da_coluna, flags=re.IGNORECASE) + match_mes = re.search(r'^Mês do Período', nome_da_coluna, flags=re.IGNORECASE) + match_reg = re.search(r'^REG', nome_da_coluna, flags=re.IGNORECASE) + match_cfop = re.search(r'^CFOP', nome_da_coluna, flags=re.IGNORECASE) + match_nbc = re.search(r'NAT_BC_CRED', nome_da_coluna, flags=re.IGNORECASE) + match_tipo = re.search(r'TIPO_ITEM', nome_da_coluna, flags=re.IGNORECASE) + match_mod = re.search(r'COD_MOD', nome_da_coluna, flags=re.IGNORECASE) + match_data = re.search(r'^DT_|Data', nome_da_coluna, flags=re.IGNORECASE) + match_chave = re.search(r'^CHV_|Chave Eletrônica', nome_da_coluna, flags=re.IGNORECASE) + match_ncm = re.search(r'COD_NCM', nome_da_coluna, flags=re.IGNORECASE) + match_cnpj = re.search(r'CNPJ', nome_da_coluna, flags=re.IGNORECASE) + match_cpf = re.search(r'CPF', nome_da_coluna, flags=re.IGNORECASE) + + match_cst_contib = re.search(r'^CST_(PIS|COFINS)|CST_PIS_COFINS', nome_da_coluna, flags=re.IGNORECASE) + match_cst_icms = re.search(r'^CST_ICMS', nome_da_coluna, flags=re.IGNORECASE) + + # https://www.geeksforgeeks.org/switch-case-in-python-replacement/ + # Ao invés de usar vários 'if/elif/elif/elif/.../else', usar o dict switcher[chave] = valor, + # tal que switcher.get(True, 'default value') retorna o valor da última chave True. + # bool(match_linha) retorna True ou False. + switcher = { + bool(match_linha): self.formatar_linhas, + bool(match_mes): self.formatar_mes, + bool(match_reg): self.formatar_registro, + bool(match_cfop): self.formatar_cfop, + bool(match_nbc): self.formatar_nbc, + bool(match_tipo): self.formatar_tipo, + bool(match_mod): self.formatar_mod, + bool(match_cst_contib): self.formatar_cst_contrib, + bool(match_cst_icms): self.formatar_cst_icms, + bool(match_data): CampoData.formatar, + bool(match_chave): CampoChaveEletronica.formatar, + bool(match_ncm): CampoNCM.formatar, + bool(match_cnpj): CampoCNPJ.formatar, + bool(match_cpf): CampoCPF.formatar, + bool(match_cnpj and match_cpf): CampoCPFouCNPJ.formatar, + } + + # Caso não ocorra nenhum match, retornar default value = self.funcao_identidade + self.dicionario[nome_da_coluna] = switcher.get(True, self.funcao_identidade) + + #print(f'{switcher = } ; {nome_da_coluna = } ; {bool(match_data) = } ; {self.dicionario[nome_da_coluna] = } \n') + #sleep(0.5) + + if self.verbose: + for idx, key in enumerate(sorted(self.dicionario.keys()),1): + print(f'{key:>40}: [{idx:>2}] {self.dicionario[key]}') + + def formatar_valores_das_colunas(self): + + for nome_da_coluna in self.lista_de_colunas: + + match_n_center = re.search(r'Linha|NUM_ITEM', nome_da_coluna, flags=re.IGNORECASE) + match_n_right = re.search(r'NUM_DOC', nome_da_coluna, flags=re.IGNORECASE) + match_valor = re.search(r'VL|Valor', nome_da_coluna, flags=re.IGNORECASE) + match_aliquota = re.search(r'Aliq', nome_da_coluna, flags=re.IGNORECASE) + match_data = re.search(r'Data|DT_', nome_da_coluna, flags=re.IGNORECASE) + + self.dicionario[nome_da_coluna] = self.funcao_identidade + + # Estes vários if/elif/elif/... são executados apenas uma vez na execução do método/função. + if match_n_center or match_n_right or match_valor or match_aliquota: + self.dicionario[nome_da_coluna] = self.formatar_valores_reais + elif match_data: + self.dicionario[nome_da_coluna] = self.formatar_datas + + def formatar_colunas_do_arquivo_excel(self,workbook): + + format_default = workbook.add_format() + format_n_center = workbook.add_format({'num_format': '0', 'align':'center'}) + format_n_right = workbook.add_format({'num_format': '0', 'align':'right'}) + format_valor = workbook.add_format({'num_format': '#,##0.00', 'align':'right'}) + format_aliquota = workbook.add_format({'num_format': '#,##0.0000', 'align':'center'}) + format_data = workbook.add_format({'num_format': 'dd/mm/yyyy', 'align':'center'}) + format_center = workbook.add_format({'align':'center'}) + + for nome_da_coluna in self.lista_de_colunas: + + match_n_center = re.search(r'Linha|NUM_ITEM', nome_da_coluna, flags=re.IGNORECASE) + match_n_right = re.search(r'NUM_DOC', nome_da_coluna, flags=re.IGNORECASE) + match_valor = re.search(r'VL|Valor', nome_da_coluna, flags=re.IGNORECASE) + match_aliquota = re.search(r'Aliq', nome_da_coluna, flags=re.IGNORECASE) + match_data = re.search(r'Data|DT_', nome_da_coluna, flags=re.IGNORECASE) + match_center = re.search(r'Período|Operação', nome_da_coluna, flags=re.IGNORECASE) + + switcher = { + bool(match_n_center): format_n_center, + bool(match_n_right): format_n_right, + bool(match_valor): format_valor, + bool(match_aliquota): format_aliquota, + bool(match_data): format_data, + bool(match_center): format_center, + } + + # Caso não ocorra nenhum match, retornar default value = format_default + self.dicionario[nome_da_coluna] = switcher.get(True, format_default) From b4900f802e946f2229904c02b06d4c7696c35ba1 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:23:36 -0300 Subject: [PATCH 24/52] =?UTF-8?q?corre=C3=A7=C3=A3o=20do=20d=C3=ADgito=20v?= =?UTF-8?q?erificador=20do=20cpf=20teste?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/pis_cofins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pis_cofins.py b/test/pis_cofins.py index 7617c62..fe2e27a 100644 --- a/test/pis_cofins.py +++ b/test/pis_cofins.py @@ -18,7 +18,7 @@ class TestSpedPisCofins(unittest.TestCase): def test_read_registro(self): txt = u"""|0000|010|0|01102016|30102016|KMEE INFORMATICA LTDA|53.939.351/0001-29|333.333.333-33|SP|222.222.222.222|1234567|5999|0123|A|1| |0001|0| -|0100|Daniel Sadamo|12334532212|532212|||Rua dos ferroviario|123|Agonia|||||| +|0100|Daniel Sadamo|12334532207|532212|||Rua dos ferroviario|123|Agonia|||||| |0990|3| |C001|1| |C990|2| From 6f866eea9bd12e8db79892f632143619c630b673 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:24:53 -0300 Subject: [PATCH 25/52] renomear arquivo --- sped/relatorios/find_efd_files.py | 212 ++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100755 sped/relatorios/find_efd_files.py diff --git a/sped/relatorios/find_efd_files.py b/sped/relatorios/find_efd_files.py new file mode 100755 index 0000000..b7b6079 --- /dev/null +++ b/sped/relatorios/find_efd_files.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import re, os, glob, sys +import cchardet as chardet # pip3 install cchardet + +Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' +Data = '06 de Fevereiro de 2020 (início: 15 de Dezembro de 2020)' + +# Versão mínima exigida: python 3.6.0 +python_version = sys.version_info +if python_version < (3,6,0): + print('versão mínima exigida do python é 3.6.0') + print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) + exit() + +# Python OOP: Atributos e Métodos (def, funções) +class ReadFiles: + """Retorna um dicionário com informações dos arquivos encontrados no diretório""" + recursive = True + current_dir = os.getcwd() + seen_file = set() # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? + + def __init__(self, root_path = None, extension = None, pattern = None): + if root_path is None: + self.root_path = self.current_dir + else: + self.root_path = root_path + if extension is None: + self.extension = '*' + else: + self.extension = extension.strip('.') + if pattern is None: + self.pattern = '.' + else: + self.pattern = pattern + self.informations = {} # instance attributes, dict + + def __repr__(self): + return f'{self.__class__.__name__}(root_path = {self.root_path!r}, extension = {self.extension!r}, pattern = {self.pattern!r})' + + def get_file_extension(self,file_path): + # https://stackoverflow.com/questions/541390/extracting-extension-from-filename-in-python + _, file_extension = os.path.splitext(file_path) + return file_extension + + def get_filename(self,file_path): + # https://stackoverflow.com/questions/541390/extracting-extension-from-filename-in-python + filename = os.path.basename(file_path) + return filename + + # https://stackoverflow.com/questions/9629179/python-counting-lines-in-a-huge-10gb-file-as-fast-as-possible + def count_number_of_lines(self,file_path): + lines = 0 + try: + with open(file_path, mode='r', encoding="utf-8", errors='ignore') as filename: + for _ in filename: + lines += 1 + except FileNotFoundError: + print('O Arquivo não existe!') + return f'{lines:,}'.replace(',','.') + + # https://stackoverflow.com/questions/436220/how-to-determine-the-encoding-of-text + # https://chardet.readthedocs.io/en/latest/usage.html + # https://github.com/PyYoshi/cChardet + # iconv -f WINDOWS-1252 -t UTF-8 filename.txt # iconv - convert text from one character encoding to another + def predict_encoding(self,file_path): + '''Predict a file's encoding using cchardet''' + # import cchardet as chardet + lines = [] + my_regex = rb"^\|9999\|\d+\|" # descartar informações após a linha que contém |9999| seguido por dígitos ; b'': binary mode + with open(file_path, mode='rb') as filename: # mode 'rb': open the file as binary data + for line in filename: + match_object = re.search(my_regex, line, flags=re.IGNORECASE) + if len(lines) > 2**8 or match_object: + #print(f'{file_path = } ; {line = }') + break + lines.append(line) + rawdata = b''.join(lines) + info = chardet.detect(rawdata) # {'encoding': 'UTF-8', 'confidence': 0.9900000095367432} + encoding = info['encoding'] + if encoding is None or not re.search('UTF-8', encoding, flags=re.IGNORECASE): + encoding = 'Latin-1' + return encoding + + @property + def find_all_files(self): + # https://www.mkyong.com/python/python-how-to-list-all-files-in-a-directory/ + # https://docs.python.org/3/library/glob.html + files = [f for f in glob.glob(self.root_path + '/' + f"**/*.{self.extension}", recursive = self.recursive)] + # How to use a variable inside a regular expression? + my_regex = f"{self.pattern}" # Literal String Interpolation, "f-strings". + for file_path in files: + # path.isfile: The easiest way to check if both a file exists and if it is a file. + # seen_file: Is there a more Pythonic way to prevent adding a duplicate to a list? + if not os.path.isfile(file_path) or file_path.casefold() in self.seen_file: + continue + match_pattern = re.search(my_regex, str(file_path), flags=re.IGNORECASE) + if match_pattern: + self.seen_file.add(file_path.casefold()) + self.informations.setdefault(file_path, {})['tipo'] = 'Arquivo' + return self.informations + + @property + def find_all_efd_contrib(self): + indice = 0 + # Calling one method from another within same class in Python + return self.find_all_efd(indice) + + @property + def find_all_efd_icmsipi(self): + indice = 1 + # Calling one method from another within same class in Python + return self.find_all_efd(indice) + + def find_all_efd(self,indice=0): + if not self.informations: # How do I check if a list/dict is empty? + self.find_all_files # Calling one method from another within same class in Python + regex_efd = ["PISCOFINS", "SPED-EFD"] + efd_type = ['EFD Contribuições', 'EFD ICMS_IPI'] + idx_nome = [8,6] + idx_data = [6,4] + idx_cnpj = [9,7] + for file_path in self.informations: + encode_info = None + if not re.search(regex_efd[indice], file_path, flags=re.IGNORECASE): + continue + # Ler apenas a primeira linha para obter encode_info + with open(file_path, mode='rb') as filename: # mode 'rb': open the file as binary data + for line in filename: + info = chardet.detect(line) # {'encoding': 'UTF-8', 'confidence': 0.9900000095367432} + encode_info = info['encoding'] + #print(f'{file_path = } ; {encode_info = } ; {info = }') + break + # Ler apenas a primeira linha para obter informações do registro de abertura '0000'. + with open(file_path, mode='r', encoding=encode_info, errors='ignore') as filename: # encoding='latin-1','UTF-8' + for line in filename: + campos = line.strip().split('|') + if len(campos) <= 10: + break + campo_registro = campos[1] # A primeira linha deve conter o registro '0000' + campo_nome = campos[ idx_nome[indice] ] + campo_data = campos[ idx_data[indice] ] + campo_cnpj = campos[ idx_cnpj[indice] ] # o campo CNPJ deve conter 14 dígitos + match_regi = re.search( '0000', campo_registro) + match_cnpj = re.search(r'(\D|^)\d{14}(\D|$)', campo_cnpj) + match_data = re.search(r'(\D|^)\d{8}(\D|$)', campo_data) + if match_regi and match_cnpj and match_data: + self.informations[file_path]['tipo'] = efd_type[indice] + self.informations[file_path]['NOME'] = campo_nome + self.informations[file_path]['CNPJ'] = "%s.%s.%s/%s-%s" % (campo_cnpj[0:2],campo_cnpj[2:5],campo_cnpj[5:8],campo_cnpj[8:12],campo_cnpj[12:14]) + self.informations[file_path]['DT_INI'] = "%s/%s/%s" % (campo_data[0:2],campo_data[2:4],campo_data[4:8]) + break + # Filter a Dictionary by values in Python using dict comprehension + return {key: value for (key, value) in sorted(self.informations.items()) if value['tipo'] == efd_type[indice]} + + def get_file_info(self,file_path): + self.informations[file_path]['extensão' ] = self.get_file_extension(file_path) + self.informations[file_path]['codificação' ] = self.predict_encoding(file_path) + self.informations[file_path]['número de linhas'] = self.count_number_of_lines(file_path) + return self.informations[file_path] + +from time import time, sleep + +def Total_Execution_Time(start,end=None): + ''' + How to format elapsed time from seconds to hours, minutes, seconds and milliseconds in Python? + https://stackoverflow.com/questions/27779677/how-to-format-elapsed-time-from-seconds-to-hours-minutes-seconds-and-milliseco + https://stackoverflow.com/questions/3620943/measuring-elapsed-time-with-the-time-module/46544199 + https://blog.softhints.com/python-test-performance-and-measure-time-elapsed-in-seconds/ + ''' + if end is None: + end = time() + hours, rem = divmod(end-start, 3600) + minutes, seconds = divmod(rem, 60) + return f"{int(hours):02d}h:{int(minutes):02d}m:{seconds:07.4f}s" + + +if __name__ == '__main__': + + start = time() + + #print(f'\n{ReadFiles.__dict__ = } \n') + + lista_de_arquivos0 = ReadFiles(root_path = '.') + lista_de_arquivos1 = ReadFiles(root_path = 'EFD Contribuicoes', extension = 'txt', pattern = 'PISCOFINS') + lista_de_arquivos2 = ReadFiles(root_path = 'EFD ICMS_IPI-ADM', extension = 'txt', pattern = 'SPED-EFD' ) + + arquivos_da_efd = [lista_de_arquivos0, lista_de_arquivos1, lista_de_arquivos2] + + for lista_de_arquivos in arquivos_da_efd: + print(f'\nlista_de_arquivos = {lista_de_arquivos}:\n') + + print(f'lista_de_arquivos.find_all_files = {lista_de_arquivos.find_all_files} ; len(lista_de_arquivos.informations) = {len(lista_de_arquivos.informations)}\n') + + # SPED EFD Contrib: + for index,file_path in enumerate(lista_de_arquivos.find_all_efd_contrib,1): + print( f"{index:>6}: {file_path} ; tipo = {lista_de_arquivos.informations[file_path]['tipo']}" ) + #continue + for attribute, value in lista_de_arquivos.get_file_info(file_path).items(): + print(f'{attribute:>30}: {value}') + + # SPED EFD ICMS_IPI: + for index,file_path in enumerate(lista_de_arquivos.find_all_efd_icmsipi,1): + print( f"{index:>6}: {file_path} ; tipo = {lista_de_arquivos.informations[file_path]['tipo']}" ) + #continue + for attribute, value in lista_de_arquivos.get_file_info(file_path).items(): + print(f'{attribute:>30}: {value}') + + end = time() + print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)} \n') + From e430523707a8725fdd5b53fdc57e8d2d43136deb Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:25:23 -0300 Subject: [PATCH 26/52] renomear arquivo --- sped/relatorios/print_csv_file.py | 574 ++++++++++++++++++++++++++++++ 1 file changed, 574 insertions(+) create mode 100644 sped/relatorios/print_csv_file.py diff --git a/sped/relatorios/print_csv_file.py b/sped/relatorios/print_csv_file.py new file mode 100644 index 0000000..0e6fca7 --- /dev/null +++ b/sped/relatorios/print_csv_file.py @@ -0,0 +1,574 @@ +# -*- coding: utf-8 -*- + +Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' +Data = '01 de Março de 2020 (início: 10 de Janeiro de 2020)' + +import os, re, sys, itertools, csv +from time import time, sleep +from sped.efd.pis_cofins.arquivos import ArquivoDigital as ArquivoDigital_PIS_COFINS +from sped.efd.icms_ipi.arquivos import ArquivoDigital as ArquivoDigital_ICMS_IPI +from sped.relatorios.efd_tabelas import EFD_Tabelas +from sped.relatorios.switcher import My_Switch + +# Versão mínima exigida: python 3.6.0 +python_version = sys.version_info +if python_version < (3,6,0): + print('versão mínima exigida do python é 3.6.0') + print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) + exit() + +# Python OOP: Atributos e Métodos (def, funções) +class SPED_EFD_Info: + """ + Imprimir SPED EFD Contribuições ou ICMS_IPI no formato .csv tal que contenha + todas as informações suficientes para verificar a correção dos lançamentos ou + apuração das contribuições de PIS/COFINS ou do ICMS segundo a legislação vigente. + """ + + # class or static variable + + # Python 3 Deep Dive (Part 4 - OOP)/03. Project 1/03. Project Solution - Transaction Numbers + contador_de_linhas = itertools.count(2) # 2 é o valor inicial do contador + + ### --- registros e colunas --- ### + + # 'Data da Emissão do Documento Fiscal' + registros_de_data_emissao = ['DT_DOC', 'DT_DOC_INI', 'DT_REF_INI', 'DT_OPER'] + + # 'Data da Entrada/Aquisição/Execução ou da Saída/Prestação/Conclusão' + registros_de_data_execucao = ['DT_EXE_SERV', 'DT_E_S', 'DT_ENT', 'DT_A_P', 'DT_DOC_FIN', 'DT_REF_FIN'] + + # merge/concatenating two lists in Python + registros_de_data = ['DT_INI', 'DT_FIN'] + registros_de_data_emissao + registros_de_data_execucao + + registros_de_identificacao_do_item = ['DESCR_ITEM', 'TIPO_ITEM', 'COD_NCM'] + + registros_de_cadastro_do_participante = ['NOME_participante', 'CNPJ_participante', 'CPF_participante'] + + registros_de_plano_de_contas = ['COD_NAT_CC', 'NOME_CTA'] + + registros_de_codigo_cst = ['CST_PIS', 'CST_COFINS'] + + registros_de_chave_eletronica = ['CHV_NFE', 'CHV_CTE', 'CHV_NFSE', 'CHV_DOCe', 'CHV_CFE', 'CHV_NFE_CTE'] + + # adicionado 'VL_OPR' para EFD ICMS_IPI + registros_de_valor = ['VL_DOC', 'VL_BRT', 'VL_OPER', 'VL_OPR', 'VL_OPER_DEP', 'VL_BC_CRED', 'VL_BC_EST', + 'VL_TOT_REC', 'VL_REC_CAIXA', 'VL_REC_COMP', 'VL_REC', 'VL_ITEM'] + + # Imprimir as informações desta coluna, nesta ordem + colunas_selecionadas = [ + 'Linhas', 'Arquivo da SPED EFD', 'Nº da Linha da EFD', 'CNPJ', 'NOME', 'Mês do Período de Apuração', + 'Ano do Período de Apuração', 'Tipo de Operação', 'IND_ORIG_CRED', 'REG', 'CST_PIS_COFINS', + 'NAT_BC_CRED', 'CFOP', 'COD_PART', *registros_de_cadastro_do_participante, 'CNPJ_CPF_PART', + 'Data de Emissão', 'Data de Execução', 'COD_ITEM', *registros_de_identificacao_do_item, + 'Chave Eletrônica', 'COD_MOD', 'NUM_DOC', 'NUM_ITEM', 'COD_CTA', *registros_de_plano_de_contas, + 'Valor do Item', 'VL_BC_PIS', 'VL_BC_COFINS', 'ALIQ_PIS', 'ALIQ_COFINS', + 'VL_ISS', 'CST_ICMS', 'VL_BC_ICMS', 'ALIQ_ICMS' + ] + + # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? + registros_totais = set( + registros_de_data + registros_de_identificacao_do_item + registros_de_plano_de_contas + + registros_de_codigo_cst + registros_de_chave_eletronica + registros_de_valor + + colunas_selecionadas) + + # initialize the attributes of the class + + def __init__(self, file_path=None, encoding=None, efd_tipo=None, verbose=False): + + if file_path is None or not os.path.isfile(file_path): + raise ValueError(f'O arquivo file_path = {file_path} não é válido!') + else: + self.file_path = file_path + + if encoding is None: + self.encoding = 'UTF-8' + else: + self.encoding = encoding + + if efd_tipo is None or re.search(r'PIS|COFINS|Contrib', efd_tipo, flags=re.IGNORECASE): + self.objeto_sped = ArquivoDigital_PIS_COFINS() # instanciar objeto sped_efd + self.efd_tipo = 'efd_contribuicoes' + elif re.search(r'ICMS|IPI', efd_tipo, flags=re.IGNORECASE): + self.objeto_sped = ArquivoDigital_ICMS_IPI() # instanciar objeto sped_efd + self.efd_tipo = 'efd_icms_ipi' + else: + raise ValueError(f'efd_tipo = {efd_tipo} inválido!') + + if not isinstance(verbose, bool): + raise ValueError(f'verbose deve ser uma variável boolean (True or False). verbose = {verbose} é inválido!') + else: + self.verbose = verbose + + self.basename = os.path.basename(self.file_path) + + self.myDict = {} + + @property + def imprimir_arquivo_csv(self): + + select_object = My_Switch(type(self).registros_totais,verbose=self.verbose) + select_object.formatar_colunas_do_arquivo_csv() + self.myDict = select_object.dicionario + + self.objeto_sped.readfile(self.file_path, codificacao=self.encoding, verbose=self.verbose) + + self.info_dos_estabelecimentos = self.cadastro_dos_estabelecimentos(self.objeto_sped) + + if self.verbose: + print(f'self.info_dos_estabelecimentos = {self.info_dos_estabelecimentos} ; len(self.info_dos_estabelecimentos) = {len(self.info_dos_estabelecimentos)}\n') + + self.info_do_participante = self.cadastro_do_participante(self.objeto_sped) + + if self.verbose: + print(f'self.info_do_participante = {self.info_do_participante} ; len(self.info_do_participante) = {len(self.info_do_participante)}\n') + + self.info_do_item = self.identificacao_do_item(self.objeto_sped) + + if self.verbose: + print(f'self.info_do_item = {self.info_do_item} ; len(self.info_do_item) = {len(self.info_do_item)}\n') + + self.info_da_conta = self.plano_de_contas_contabeis(self.objeto_sped) + + if self.verbose: + print(f'self.info_da_conta = {self.info_da_conta} ; len(self.info_da_conta) = {len(self.info_da_conta)}\n') + + self.info_de_abertura = self.obter_info_de_abertura(self.objeto_sped) + + filename = os.path.splitext(self.file_path)[0] # ('./efd_info', '.py') + arquivo_csv = filename + '.csv' + + self.info_dos_blocos(self.objeto_sped, output_filename=arquivo_csv) + + def __repr__(self): + # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance + # Devo substituir 'self.__class__.static_var' por 'type(self).static_var' ? + return f'{type(self).__name__}(file_path={self.file_path!r}, encoding={self.encoding!r}, efd_tipo={self.efd_tipo!r}, verbose={self.verbose!r})' + + def formatar_valor(self,nome,val): + """ + Evitar n repetições de 'if condicao_j then A_j else B_j' tal que 1 <= j <= n, + usar dicionário: myDict[key] = funtion_key(value) + Better optimization technique using if/else or dictionary + A series of if/else statement which receives the 'string' returns the appropriate function for it. + A dictionary maintaining the key-value pair. key as strings, and values as the function objects, + and one main function to search and return the function object. + """ + # https://stackoverflow.com/questions/11445226/better-optimization-technique-using-if-else-or-dictionary + # https://softwareengineering.stackexchange.com/questions/182093/why-store-a-function-inside-a-python-dictionary/182095 + # https://stackoverflow.com/questions/9168340/using-a-dictionary-to-select-function-to-execute + try: + # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance + # val_formated = self.__class__.myDict[nome](val) + val_formated = self.myDict[nome](val) + except: + val_formated = val + #print(f'nome = {nome} ; val = {val} ; val_formated = {val_formated}') + return val_formated + + # https://radek.io/2011/07/21/static-variables-and-methods-in-python/ + @staticmethod + def natureza_da_bc_dos_creditos(cfop): + """ + http://sped.rfb.gov.br/arquivo/show/1681 + Tabela CFOP - Operações Geradoras de Créditos - Versão 1.0.0 + """ + natureza_bc = None + + # Código 01 - CFOP de 'Aquisição de Bens para Revenda' + if cfop in ['1102','1113','1117','1118','1121','1251','1403','1652','2102','2113', + '2117','2118','2121','2251','2403','2652','3102','3251','3652']: + natureza_bc = 1 + # Código 02 - CFOP de 'Aquisição de Bens Utilizados como Insumo' + elif cfop in ['1101','1111','1116','1120','1122','1126','1128','1401','1407','1556', + '1651','1653','2101','2111','2116','2120','2122','2126','2128','2401', + '2407','2556','2651','2653','3101','3126','3128','3556','3651','3653']: + natureza_bc = 2 + # Código 03 - CFOP de 'Aquisição de Serviços Utilizados como Insumos' + elif cfop in ['1124','1125','1933','2124','2125','2933']: + natureza_bc = 3 + # Código 12 - CFOP de 'Devolução de Vendas Sujeitas à Incidência Não-Cumulativa' + elif cfop in ['1201','1202','1203','1204','1410','1411','1660','1661','1662','2201', + '2202','2410','2411','2660','2661','2662']: + natureza_bc = 12 + # Código 13 - CFOP de 'Outras Operações com Direito a Crédito' + elif cfop in ['1922','2922']: + natureza_bc = 13 + + return natureza_bc + + def cadastro_dos_estabelecimentos(self,sped_efd): + """ + Registro 0140: Tabela de Cadastro de Estabelecimentos + O Registro 0140 tem por objetivo relacionar e informar os estabelecimentos da pessoa jurídica. + """ + blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. + info = {} + for registro in blocoZero.registros: + REG = registro.valores[1] + if REG != '0140': + continue + codigo_cnpj = None + for campo in registro.campos: + valor = registro.valores[campo.indice] + if campo.nome == 'CNPJ' and re.search(r'^\d{14}$', str(valor)): + codigo_cnpj = valor + break + for campo in registro.campos: + valor = registro.valores[campo.indice] + if campo.nome == 'NOME' and codigo_cnpj is not None: + info[codigo_cnpj] = valor + break + return info + + # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance + def cadastro_do_participante(self,sped_efd): + """ + Registro 0150: Tabela de Cadastro do Participante + Retorno desta função: + info_do_participante[codigo_do_participante][campo] = descricao + """ + blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. + info = {} + for registro in blocoZero.registros: + REG = registro.valores[1] + if REG != '0150': + continue + codigo_do_participante = None + for campo in registro.campos: + valor = registro.valores[campo.indice] + # Fazer distinção entre 'NOME' do Registro0000 e 'NOME' do Registro0150 + nome = campo.nome + '_participante' + if campo.nome == 'COD_PART': + codigo_do_participante = valor + info[codigo_do_participante] = {} + if nome in type(self).registros_de_cadastro_do_participante and codigo_do_participante is not None: + info[codigo_do_participante][nome] = valor + return info + + def identificacao_do_item(self,sped_efd): + """ + Registro 0200: Tabela de Identificação do Item (Produtos e Serviços) + Retorno desta função: + info_do_item[codigo_do_item][campo] = descricao + """ + blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. + info = {} + for registro in blocoZero.registros: + REG = registro.valores[1] + if REG != '0200': + continue + codigo_do_item = None + for campo in registro.campos: + valor = registro.valores[campo.indice] + if campo.nome == 'COD_ITEM': + codigo_do_item = valor + info[codigo_do_item] = {} + if campo.nome in type(self).registros_de_identificacao_do_item and codigo_do_item is not None: + info[codigo_do_item][campo.nome] = valor + return info + + def plano_de_contas_contabeis(self,sped_efd): + """ + Registro 0500: Plano de Contas Contábeis + Retorno desta função: + info_do_item[codigo_do_item][campo] = descricao + """ + blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. + info = {} + for registro in blocoZero.registros: + REG = registro.valores[1] + if REG != '0500': + continue + codigo_do_item = None + for campo in registro.campos: + valor = registro.valores[campo.indice] + if campo.nome == 'COD_CTA': + codigo_do_item = valor + info[codigo_do_item] = {} + break + for campo in registro.campos: + valor = registro.valores[campo.indice] + if campo.nome in type(self).registros_de_plano_de_contas and codigo_do_item is not None: + info[codigo_do_item][campo.nome] = valor + return info + + def obter_info_de_abertura(self,sped_efd): + registro = sped_efd._registro_abertura + REG = registro.valores[1] + nivel = registro.nivel + + # Utilizar uma combinação de valores para identificar univocamente um item. + combinacao = 'registro de abertura' + + info_de_abertura = {} + + # https://www.geeksforgeeks.org/python-creating-multidimensional-dictionary/ + info_de_abertura.setdefault(nivel, {}).setdefault(combinacao, {})['Nível Hierárquico'] = nivel + + if self.verbose: + print(f'registro.as_line() = {registro.as_line()} ; REG = {REG} ; nivel = {nivel}') + print(f'info_de_abertura = {info_de_abertura}\n') + + for campo in registro.campos: + + valor = registro.valores[campo.indice] + + if campo.nome in type(self).colunas_selecionadas: + info_de_abertura[nivel][combinacao][campo.nome] = valor + if campo.nome == 'DT_INI': + ddmmaaaa = registro.valores[campo.indice] + info_de_abertura[nivel][combinacao]['Data de Emissão'] = valor + info_de_abertura[nivel][combinacao]['Mês do Período de Apuração'] = ddmmaaaa[2:4] + info_de_abertura[nivel][combinacao]['Ano do Período de Apuração'] = ddmmaaaa[4:8] + if campo.nome == 'DT_FIN': + info_de_abertura[nivel][combinacao]['Data de Execução'] = valor + if self.verbose: + valor_formatado = self.formatar_valor(nome=campo.nome, val=valor) + print(f'campo.indice = {campo.indice:>2} ; campo.nome = {campo.nome:>22} ; registro.valores[{campo.indice:>2}] = {valor:<50} ; valor_formatado = {valor_formatado}') + + if self.verbose: + print(f'\ninfo_de_abertura = {info_de_abertura}\n') + + return info_de_abertura + + def adicionar_informacoes(self,dict_info): + """ + Adicionar informações em dict_info + Formatar alguns de seus campos com o uso de tabelas ou funções + """ + dict_info['Arquivo da SPED EFD'] = self.basename + dict_info['Linhas'] = next(type(self).contador_de_linhas) + + # re.search: find something anywhere in the string and return a match object. + if 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS']): + cst = int(dict_info['CST_PIS_COFINS']) + if 1 <= cst <= 49: + dict_info['Tipo de Operação'] = 'Saída' + elif 50 <= cst <= 99: + dict_info['Tipo de Operação'] = 'Entrada' + + # adicionar informação de NAT_BC_CRED para os créditos (50 <= cst <= 66) + # quando houver informação do CFOP e NAT_BC_CRED estiver vazio. + if ('CFOP' in dict_info and 'NAT_BC_CRED' in dict_info + and re.search(r'\d{4}', dict_info['CFOP']) and len(dict_info['NAT_BC_CRED']) == 0 + #and ( re.search(r'[1-9]', dict_info['ALIQ_PIS']) or re.search(r'[1-9]', dict_info['ALIQ_COFINS']) ) # aliq_cofins > 0 + and 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS'])): + cfop = str(dict_info['CFOP']) + cst = int(dict_info['CST_PIS_COFINS']) + if 50 <= cst <= 66: + dict_info['NAT_BC_CRED'] = type(self).natureza_da_bc_dos_creditos(cfop) + + # Índice de Origem do Crédito: Leia os comentários do 'Registro M100: Crédito de PIS/Pasep Relativo ao Período'. + # Os códigos vinculados à importação (108, 208 e 308) são obtidos através da informação de CFOP + # iniciado em 3 (quando existente) ou pelo campo IND_ORIG_CRED nos demais casos. + indicador_de_origem = 'Mercado Interno' # Default Value: 0 - Mercado Interno ; 1 - Mercado Externo (Importação). + if (('CFOP' in dict_info and re.search(r'^3\d{3}', dict_info['CFOP'])) or + ('IND_ORIG_CRED' in dict_info and dict_info['IND_ORIG_CRED'] == '1')): + indicador_de_origem = 'Mercado Externo (Importação)' + dict_info['IND_ORIG_CRED'] = indicador_de_origem + + # adicionar informação de cadastro do participante obtido do Registro 0150 + # info_do_participante[codigo_do_participante][campo] = descricao + if 'COD_PART' in dict_info and dict_info['COD_PART'] in self.info_do_participante: + codigo_do_participante = dict_info['COD_PART'] + for campo in self.info_do_participante[codigo_do_participante]: + dict_info[campo] = self.info_do_participante[codigo_do_participante][campo] + + # adicionar informação de identificação do item obtido do Registro 0200 + # info_do_item[codigo_do_item][campo] = descricao + if 'COD_ITEM' in dict_info and dict_info['COD_ITEM'] in self.info_do_item: + codigo_do_item = dict_info['COD_ITEM'] + for campo in self.info_do_item[codigo_do_item]: + dict_info[campo] = self.info_do_item[codigo_do_item][campo] + + # adicionar informação do plano de contas obtido do Registro 0500 + # info_da_conta[codigo_da_conta][campo] = descricao + if 'COD_CTA' in dict_info and dict_info['COD_CTA'] in self.info_da_conta: + codigo_da_conta = dict_info['COD_CTA'] + for campo in self.info_da_conta[codigo_da_conta]: + val = str(self.info_da_conta[codigo_da_conta][campo]) + if campo == 'COD_NAT_CC' and re.search(r'\d{1,2}', val): + val = val.zfill(2) # val = f'{int(val):02d}' + val = val + ' - ' + EFD_Tabelas.tabela_natureza_da_conta[val] + dict_info[campo] = val + + # Ao final, formatar alguns valores dos campos + for campo in dict_info.copy(): + valor_formatado = self.formatar_valor(nome=campo, val=dict_info[campo]) + dict_info[campo] = valor_formatado + + return dict_info + + def info_dos_blocos(self,sped_efd,output_filename): + + my_regex = r'^[A-K]' # Ler os blocos da A a K. + + campos_necessarios = ['CST_PIS', 'CST_COFINS', 'VL_BC_PIS', 'VL_BC_COFINS'] + # Bastam os seguintes campos, desde que os registros de PIS/PASEP ocorram sempre anteriores aos registros de COFINS: + # campos_necessarios = ['CST_COFINS', 'VL_BC_COFINS'] + + if self.efd_tipo == 'efd_icms_ipi': + campos_necessarios = ['CST_ICMS', 'VL_BC_ICMS'] + + # https://docs.python.org/3/library/csv.html + with open(output_filename, 'w', newline='', encoding='utf-8', errors='ignore') as csvfile: + + writer = csv.writer(csvfile, delimiter=';') + writer.writerow(type(self).colunas_selecionadas) # imprimir nomes das colunas apenas uma vez + + for key in sped_efd._blocos.keys(): + + match_bloco = re.search(my_regex, key, flags=re.IGNORECASE) + if not match_bloco: + continue + + bloco = sped_efd._blocos[key] + count = 1 + + info = self.info_de_abertura + + for registro in bloco.registros: + + REG = registro.valores[1] + + try: + nivel_anterior = nivel + num_de_campos_anterior = num_de_campos + except: + nivel_anterior = registro.nivel + 1 + num_de_campos_anterior = len(registro.campos) + 1 + + nivel = registro.nivel # nível atual + num_de_campos = len(registro.campos) + + cst_pis = '' # 2 caracteres + cst_cofins = '' # 2 caracteres + cst_icms = '' # 3 caracteres + cfop = 'cfop' # 4 caracteres + valor_item = 'valor_item' + + for campo in registro.campos: + if campo.nome == 'CST_PIS': + cst_pis = registro.valores[campo.indice] + if campo.nome == 'CST_COFINS': + cst_cofins = registro.valores[campo.indice] + if campo.nome == 'CST_ICMS': + cst_icms = registro.valores[campo.indice] + if campo.nome == 'CFOP': + cfop = registro.valores[campo.indice] + if campo.nome in type(self).registros_de_valor: + valor_item = registro.valores[campo.indice] + + cst_contribuicao = max(cst_pis,cst_cofins) + + # Utilizar uma combinação de valores para identificar univocamente um item. + combinacao = f'{cst_contribuicao}_{cst_icms}_{cfop}_{valor_item}' + + if self.verbose: + print(f'\ncount = {count:>2} ; key = {key} ; REG = {REG} ; nivel_anterior = {nivel_anterior} ; nivel = {nivel} ; ', end='') + print(f'num_de_campos_anterior = {num_de_campos_anterior} ; num_de_campos = {num_de_campos} ; ', end='') + print(f'cst_pis = {cst_pis} ; cst_cofins = {cst_cofins} ; cst_contribuicao = {cst_contribuicao}') + print(f'registro.as_line() = {registro.as_line()}') + + # As informações do pai e respectivos filhos devem ser apagadas quando + # o nivel hierárquico regride dos filhos para pais diferentes. + if nivel < nivel_anterior or (nivel == nivel_anterior and num_de_campos < num_de_campos_anterior): + if self.verbose: + if nivel < nivel_anterior: + print(f'\n nivel atual: nivel = {nivel} < nivel_anterior = {nivel_anterior} ; ', end='') + if nivel == nivel_anterior and num_de_campos < num_de_campos_anterior: + print(f'\n numero de campos atual: num_de_campos = {num_de_campos} < num_de_campos_anterior = {num_de_campos_anterior} ; ', end='') + print(f'deletar informações em info a partir do nível {nivel} em diante:') + + # Delete items from dictionary while iterating: + # https://www.geeksforgeeks.org/python-delete-items-from-dictionary-while-iterating/ + for nv in list(info): + if nv >= nivel: + del info[nv] + if self.verbose: + print(f'\t *** deletar informações do nível {nv}: del info[{nv}] ***') + print() if self.verbose else 0 + + # https://www.geeksforgeeks.org/python-creating-multidimensional-dictionary/ + info.setdefault(nivel, {}).setdefault(combinacao, {})['Nível Hierárquico'] = nivel + info[nivel][combinacao]['Valor do Item'] = valor_item + info[nivel][combinacao]['CST_PIS_COFINS'] = cst_contribuicao + + for campo in registro.campos: + + try: + valor = registro.valores[campo.indice] + except: + valor = f'{REG}[{campo.indice}:{campo.nome}] sem valor definido' + + if self.verbose: + valor_formatado = self.formatar_valor(nome=campo.nome, val=valor) + print(f'campo.indice = {campo.indice:>2} ; campo.nome = {campo.nome:>22} ; registro.valores[{campo.indice:>2}] = {valor:<50} ; valor_formatado = {valor_formatado}') + + if campo.nome not in type(self).registros_totais: # filtrar registros_totais + continue + + # reter em info{} as informações dos registros contidos em registros_totais + info[nivel][combinacao][campo.nome] = valor + + # Informar os campos em registros_de_data_emissao na coluna 'Data de Emissão'. + if campo.nome in type(self).registros_de_data_emissao: + info[nivel][combinacao]['Data de Emissão'] = valor + # Informar os campos em registros_de_data_execucao na coluna 'Data de Execução'. + if campo.nome in type(self).registros_de_data_execucao: + info[nivel][combinacao]['Data de Execução'] = valor + # Informar os campos de chave eletrônica de 44 dígitos na coluna 'Chave Eletrônica'. + if campo.nome in type(self).registros_de_chave_eletronica: + info[nivel][combinacao]['Chave Eletrônica'] = valor + # Informar nomes dos estabelecimentos de cada CNPJ + if campo.nome == 'CNPJ' and valor in self.info_dos_estabelecimentos: + info[nivel][combinacao]['NOME'] = self.info_dos_estabelecimentos[valor] + + if self.verbose: + print(f'\n-->info[nivel][combinacao] = info[{nivel}][{combinacao}] = {info[nivel][combinacao]}\n') + + #https://stackoverflow.com/questions/3931541/how-to-check-if-all-of-the-following-items-are-in-a-list + # set(['a', 'c']).issubset(['a', 'b', 'c', 'd']) or set(lista1).issubset(lista2) + + if set(campos_necessarios).issubset( info[nivel][combinacao] ): + + # import this: Zen of Python: Flat is better than nested. + flattened_info = {} # eliminar os dois niveis [nivel][combinacao] e trazer todas as informações para apenas uma dimensão. + seen_column = set() # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? + + # em info{} há os registros_totais, em flattened_info{} apenas as colunas para impressao + for coluna in type(self).colunas_selecionadas: + flattened_info[coluna] = '' # atribuir valor inicial para todas as colunas + + if coluna in info[nivel][combinacao]: + flattened_info[coluna] = info[nivel][combinacao][coluna] # eliminar os dois niveis [nivel][combinacao] + seen_column.add(coluna) + if self.verbose: + print(f'nivel = {nivel:<10} ; combinacao = {combinacao:25} ; coluna = {coluna:>35} = {info[nivel][combinacao][coluna]:<35} ; info[nivel][combinacao] = {info[nivel][combinacao]}') + continue + + for nv in sorted(info,reverse=True): # nível em ordem decrescente + if coluna in seen_column: # informações já obtidas + break # as informações obtidas do nível mais alto prevalecerá + for comb in info[nv]: + if coluna in info[nv][comb]: + flattened_info[coluna] = info[nv][comb][coluna] # eliminar os dois niveis [nivel][combinacao] + seen_column.add(coluna) + if self.verbose: + print(f'nivel = {nivel} ; nv = {nv} ; combinacao = {comb:25} ; coluna = {coluna:>35} = {info[nv][comb][coluna]:<35} ; info[nivel][combinacao] = {info[nv][comb]}') + + print() if self.verbose else 0 + + flattened_info['Nº da Linha da EFD'] = registro.numero_da_linha + + # Adicionar informações em flattened_info ou formatar alguns de seus campos com o uso de tabelas ou funções + flattened_info = self.adicionar_informacoes(flattened_info) + + writer.writerow( flattened_info.values() ) + + # Se verbose == True, limitar tamanho do arquivo impresso + # Imprimir apenas os 20 primeiros registros de cada Bloco + count += 1 + if self.verbose and count > 20: + break From d8dd94edfff3b4654312696f967fd57ec38edc7f Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:26:13 -0300 Subject: [PATCH 27/52] arquivos deletados --- sped/relatorios/efd_info.py | 825 -------------------------------- sped/relatorios/efd_read_dir.py | 212 -------- 2 files changed, 1037 deletions(-) delete mode 100644 sped/relatorios/efd_info.py delete mode 100755 sped/relatorios/efd_read_dir.py diff --git a/sped/relatorios/efd_info.py b/sped/relatorios/efd_info.py deleted file mode 100644 index c4699b9..0000000 --- a/sped/relatorios/efd_info.py +++ /dev/null @@ -1,825 +0,0 @@ -# -*- coding: utf-8 -*- - -Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '28 de Fevereiro de 2020 (início: 10 de Janeiro de 2020)' - -import os, re, sys, itertools, csv -import xlsxwriter # pip install xlsxwriter -from datetime import datetime -from time import time, sleep -from sped.efd.pis_cofins.arquivos import ArquivoDigital as ArquivoDigital_PIS_COFINS -from sped.efd.icms_ipi.arquivos import ArquivoDigital as ArquivoDigital_ICMS_IPI -from sped.relatorios.efd_tabelas import EFD_Tabelas -from sped.campos import CampoData, CampoCNPJ, CampoCPF, CampoCPFouCNPJ, CampoChaveEletronica, CampoNCM - -# Versão mínima exigida: python 3.6.0 -python_version = sys.version_info -if python_version < (3,6,0): - print('versão mínima exigida do python é 3.6.0') - print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) - exit() - -class My_Switch: - """ - Definir, apenas uma vez, um dicionário ao invés de utilizar vários 'if/then/else' a cada - execução de formatar_valor(): - dict[key] = funtion_key(value) - Ao escolher uma chave, o dicionário aplica uma função (que depende da chave) sobre o valor - Esta construção possui Ordem O(1). - Caso fossem utilizados vários if/then/else (ou switch) a ordem seria O(N), que é mais lento! - """ - - @staticmethod - def funcao_identidade(chave): - return chave - - @staticmethod - def formatar_linhas(numero): - return f'{int(numero):09d}' - - @staticmethod - def formatar_mes(mes_num): - try: - mes_num = f'{int(mes_num):02d}' - return f'{EFD_Tabelas.tabela_mes_nominal[mes_num]}' - except: - return mes_num - - @staticmethod - def formatar_registro(registro): - try: - return f'{registro} - {EFD_Tabelas.tabela_info_do_registro[registro]}' - except: - reg = registro[0] - return f'{registro} - {EFD_Tabelas.tabela_info_do_registro[reg]}' - - @staticmethod - def formatar_cfop(cfop): - try: - cfop = f'{int(cfop):04d}' - return f'{cfop} - {EFD_Tabelas.tabela_cfop_descricao[cfop]}' - except: - return cfop - - @staticmethod - def formatar_cst_contrib(codigo_cst): - try: - codigo_cst = f'{int(codigo_cst):02d}' - return f'{codigo_cst} - {EFD_Tabelas.tabela_cst_contrib[codigo_cst]}' - except: - return codigo_cst - - @staticmethod - def formatar_cst_icms(codigo_cst): - try: - codigo_cst = f'{int(codigo_cst):03d}' - return f'{codigo_cst} - {EFD_Tabelas.tabela_cst_icms[codigo_cst]}' - except: - return codigo_cst - - @staticmethod - def formatar_nbc(natureza_bc): - try: - natureza_bc = f'{int(natureza_bc):02d}' - return f'{natureza_bc} - {EFD_Tabelas.tabela_bc_do_credito[natureza_bc]}' - except: - return natureza_bc - - @staticmethod - def formatar_tipo(tipo_do_item): - try: - tipo_do_item = f'{int(tipo_do_item):02d}' - return f'{tipo_do_item} - {EFD_Tabelas.tabela_tipo_do_item[tipo_do_item]}' - except: - return tipo_do_item - - @staticmethod - def formatar_mod(doc_fiscal): - try: - return f'{doc_fiscal} - {EFD_Tabelas.tabela_modelos_documentos_fiscais[doc_fiscal]}' - except: - return doc_fiscal - - @staticmethod - def formatar_valores_reais(valor): - try: - return float(valor) - except: - valor = valor.replace( '.', '' ) # 4.218.239,19 --> 4218239,19 - valor = valor.replace( ',', '.' ) # 4218239,19 --> 4218239.19 - return float(valor) - - @staticmethod - def formatar_datas(data): - date_time = datetime.strptime(data, "%d/%m/%Y") # dd/mm/aaaa - return date_time - - # initialize the attributes of the class - - def __init__(self, lista_de_colunas, verbose=False): - - self.lista_de_colunas = lista_de_colunas - - self.verbose = verbose - - self.dicionario = {} - - def formatar_colunas_do_arquivo_csv(self): - - for nome_da_coluna in self.lista_de_colunas: - - match_linha = re.search(r'^Linhas', nome_da_coluna, flags=re.IGNORECASE) - match_mes = re.search(r'^Mês do Período', nome_da_coluna, flags=re.IGNORECASE) - match_reg = re.search(r'^REG', nome_da_coluna, flags=re.IGNORECASE) - match_cfop = re.search(r'^CFOP', nome_da_coluna, flags=re.IGNORECASE) - match_nbc = re.search(r'NAT_BC_CRED', nome_da_coluna, flags=re.IGNORECASE) - match_tipo = re.search(r'TIPO_ITEM', nome_da_coluna, flags=re.IGNORECASE) - match_mod = re.search(r'COD_MOD', nome_da_coluna, flags=re.IGNORECASE) - match_data = re.search(r'^DT_|Data', nome_da_coluna, flags=re.IGNORECASE) - match_chave = re.search(r'^CHV_|Chave Eletrônica', nome_da_coluna, flags=re.IGNORECASE) - match_ncm = re.search(r'COD_NCM', nome_da_coluna, flags=re.IGNORECASE) - match_cnpj = re.search(r'CNPJ', nome_da_coluna, flags=re.IGNORECASE) - match_cpf = re.search(r'CPF', nome_da_coluna, flags=re.IGNORECASE) - - match_cst_contib = re.search(r'^CST_(PIS|COFINS)|CST_PIS_COFINS', nome_da_coluna, flags=re.IGNORECASE) - match_cst_icms = re.search(r'^CST_ICMS', nome_da_coluna, flags=re.IGNORECASE) - - # https://www.geeksforgeeks.org/switch-case-in-python-replacement/ - # Ao invés de usar vários 'if/elif/elif/elif/.../else', usar o dict switcher[chave] = valor, - # tal que switcher.get(True, 'default value') retorna o valor da última chave True. - # bool(match_linha) retorna True ou False. - switcher = { - bool(match_linha): self.formatar_linhas, - bool(match_mes): self.formatar_mes, - bool(match_reg): self.formatar_registro, - bool(match_cfop): self.formatar_cfop, - bool(match_nbc): self.formatar_nbc, - bool(match_tipo): self.formatar_tipo, - bool(match_mod): self.formatar_mod, - bool(match_cst_contib): self.formatar_cst_contrib, - bool(match_cst_icms): self.formatar_cst_icms, - bool(match_data): CampoData.formatar, - bool(match_chave): CampoChaveEletronica.formatar, - bool(match_ncm): CampoNCM.formatar, - bool(match_cnpj): CampoCNPJ.formatar, - bool(match_cpf): CampoCPF.formatar, - bool(match_cnpj and match_cpf): CampoCPFouCNPJ.formatar, - } - - # Caso não ocorra nenhum match, retornar default value = self.funcao_identidade - self.dicionario[nome_da_coluna] = switcher.get(True, self.funcao_identidade) - - #print(f'{switcher = } ; {nome_da_coluna = } ; {bool(match_data) = } ; {self.dicionario[nome_da_coluna] = } \n') - #sleep(0.5) - - if self.verbose: - for idx, key in enumerate(sorted(self.dicionario.keys()),1): - print(f'{key:>40}: [{idx:>2}] {self.dicionario[key]}') - - def formatar_valores_das_colunas(self): - - for nome_da_coluna in self.lista_de_colunas: - - match_n_center = re.search(r'Linha|NUM_ITEM', nome_da_coluna, flags=re.IGNORECASE) - match_n_right = re.search(r'NUM_DOC', nome_da_coluna, flags=re.IGNORECASE) - match_valor = re.search(r'VL|Valor', nome_da_coluna, flags=re.IGNORECASE) - match_aliquota = re.search(r'Aliq', nome_da_coluna, flags=re.IGNORECASE) - match_data = re.search(r'Data|DT_', nome_da_coluna, flags=re.IGNORECASE) - - self.dicionario[nome_da_coluna] = self.funcao_identidade - - # Estes vários if/elif/elif/... são executados apenas uma vez na execução do método/função. - if match_n_center or match_n_right or match_valor or match_aliquota: - self.dicionario[nome_da_coluna] = self.formatar_valores_reais - elif match_data: - self.dicionario[nome_da_coluna] = self.formatar_datas - - def formatar_colunas_do_arquivo_excel(self,workbook): - - format_default = workbook.add_format() - format_n_center = workbook.add_format({'num_format': '0', 'align':'center'}) - format_n_right = workbook.add_format({'num_format': '0', 'align':'right'}) - format_valor = workbook.add_format({'num_format': '#,##0.00', 'align':'right'}) - format_aliquota = workbook.add_format({'num_format': '#,##0.0000', 'align':'center'}) - format_data = workbook.add_format({'num_format': 'dd/mm/yyyy', 'align':'center'}) - format_center = workbook.add_format({'align':'center'}) - - for nome_da_coluna in self.lista_de_colunas: - - match_n_center = re.search(r'Linha|NUM_ITEM', nome_da_coluna, flags=re.IGNORECASE) - match_n_right = re.search(r'NUM_DOC', nome_da_coluna, flags=re.IGNORECASE) - match_valor = re.search(r'VL|Valor', nome_da_coluna, flags=re.IGNORECASE) - match_aliquota = re.search(r'Aliq', nome_da_coluna, flags=re.IGNORECASE) - match_data = re.search(r'Data|DT_', nome_da_coluna, flags=re.IGNORECASE) - match_center = re.search(r'Período|Operação', nome_da_coluna, flags=re.IGNORECASE) - - switcher = { - bool(match_n_center): format_n_center, - bool(match_n_right): format_n_right, - bool(match_valor): format_valor, - bool(match_aliquota): format_aliquota, - bool(match_data): format_data, - bool(match_center): format_center, - } - - # Caso não ocorra nenhum match, retornar default value = format_default - self.dicionario[nome_da_coluna] = switcher.get(True, format_default) - - -# Python OOP: Atributos e Métodos (def, funções) -class SPED_EFD_Info: - """ - Imprimir SPED EFD Contribuições ou ICMS_IPI nos formatos .csv e .xlsx tal que - contenha todas as informações suficientes para verificar a correção dos lançamentos - ou apuração das contribuições de PIS/COFINS ou do ICMS segundo a legislação vigente. - """ - - # class or static variable - - # Python 3 Deep Dive (Part 4 - OOP)/03. Project 1/03. Project Solution - Transaction Numbers - contador_de_linhas = itertools.count(2) # 2 é o valor inicial do contador - - ### --- registros e colunas --- ### - - # 'Data da Emissão do Documento Fiscal' - registros_de_data_emissao = ['DT_DOC', 'DT_DOC_INI', 'DT_REF_INI', 'DT_OPER'] - - # 'Data da Entrada/Aquisição/Execução ou da Saída/Prestação/Conclusão' - registros_de_data_execucao = ['DT_EXE_SERV', 'DT_E_S', 'DT_ENT', 'DT_A_P', 'DT_DOC_FIN', 'DT_REF_FIN'] - - # merge/concatenating two lists in Python - registros_de_data = ['DT_INI', 'DT_FIN'] + registros_de_data_emissao + registros_de_data_execucao - - registros_de_identificacao_do_item = ['DESCR_ITEM', 'TIPO_ITEM', 'COD_NCM'] - - registros_de_cadastro_do_participante = ['NOME_participante', 'CNPJ_participante', 'CPF_participante'] - - registros_de_plano_de_contas = ['COD_NAT_CC', 'NOME_CTA'] - - registros_de_codigo_cst = ['CST_PIS', 'CST_COFINS'] - - registros_de_chave_eletronica = ['CHV_NFE', 'CHV_CTE', 'CHV_NFSE', 'CHV_DOCe', 'CHV_CFE', 'CHV_NFE_CTE'] - - # adicionado 'VL_OPR' para EFD ICMS_IPI - registros_de_valor = ['VL_DOC', 'VL_BRT', 'VL_OPER', 'VL_OPR', 'VL_OPER_DEP', 'VL_BC_CRED', 'VL_BC_EST', - 'VL_TOT_REC', 'VL_REC_CAIXA', 'VL_REC_COMP', 'VL_REC', 'VL_ITEM'] - - # Imprimir as informações desta coluna, nesta ordem - colunas_selecionadas = [ - 'Linhas', 'Arquivo da SPED EFD', 'Nº da Linha da EFD', 'CNPJ', 'NOME', 'Mês do Período de Apuração', - 'Ano do Período de Apuração', 'Tipo de Operação', 'IND_ORIG_CRED', 'REG', 'CST_PIS_COFINS', - 'NAT_BC_CRED', 'CFOP', 'COD_PART', *registros_de_cadastro_do_participante, 'CNPJ_CPF_PART', - 'Data de Emissão', 'Data de Execução', 'COD_ITEM', *registros_de_identificacao_do_item, - 'Chave Eletrônica', 'COD_MOD', 'NUM_DOC', 'NUM_ITEM', 'COD_CTA', *registros_de_plano_de_contas, - 'Valor do Item', 'VL_BC_PIS', 'VL_BC_COFINS', 'ALIQ_PIS', 'ALIQ_COFINS', - 'VL_ISS', 'CST_ICMS', 'VL_BC_ICMS', 'ALIQ_ICMS' - ] - - # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? - registros_totais = set( - registros_de_data + registros_de_identificacao_do_item + registros_de_plano_de_contas + - registros_de_codigo_cst + registros_de_chave_eletronica + registros_de_valor + - colunas_selecionadas) - - # initialize the attributes of the class - - def __init__(self, file_path=None, encoding=None, efd_tipo=None, verbose=False): - - if file_path is None or not os.path.isfile(file_path): - raise ValueError(f'O arquivo file_path = {file_path} não é válido!') - else: - self.file_path = file_path - - if encoding is None: - self.encoding = 'UTF-8' - else: - self.encoding = encoding - - if efd_tipo is None or re.search(r'PIS|COFINS|Contrib', efd_tipo, flags=re.IGNORECASE): - self.objeto_sped = ArquivoDigital_PIS_COFINS() # instanciar objeto sped_efd - self.efd_tipo = 'efd_contribuicoes' - elif re.search(r'ICMS|IPI', efd_tipo, flags=re.IGNORECASE): - self.objeto_sped = ArquivoDigital_ICMS_IPI() # instanciar objeto sped_efd - self.efd_tipo = 'efd_icms_ipi' - else: - raise ValueError(f'efd_tipo = {efd_tipo} inválido!') - - if not isinstance(verbose, bool): - raise ValueError(f'verbose deve ser uma variável boolean (True or False). verbose = {verbose} é inválido!') - else: - self.verbose = verbose - - self.basename = os.path.basename(self.file_path) - - self.myDict = {} - - @property - def imprimir_informacoes(self): - - select_object = My_Switch(type(self).registros_totais,verbose=self.verbose) - select_object.formatar_colunas_do_arquivo_csv() - self.myDict = select_object.dicionario - - self.objeto_sped.readfile(self.file_path, codificacao=self.encoding, verbose=self.verbose) - - self.info_do_participante = self.cadastro_do_participante(self.objeto_sped) - - if self.verbose: - print(f'self.info_do_participante = {self.info_do_participante} ; len(self.info_do_participante) = {len(self.info_do_participante)}\n') - - self.info_do_item = self.identificacao_do_item(self.objeto_sped) - - if self.verbose: - print(f'self.info_do_item = {self.info_do_item} ; len(self.info_do_item) = {len(self.info_do_item)}\n') - - self.info_da_conta = self.plano_de_contas_contabeis(self.objeto_sped) - - if self.verbose: - print(f'self.info_da_conta = {self.info_da_conta} ; len(self.info_da_conta) = {len(self.info_da_conta)}\n') - - self.info_de_abertura = self.obter_info_de_abertura(self.objeto_sped) - - filename = os.path.splitext(self.file_path)[0] # ('./efd_info', '.py') - arquivo_csv = filename + '.csv' - arquivo_excel = filename + '.xlsx' - - self.imprimir_informacoes_da_efd(self.objeto_sped, output_filename=arquivo_csv) - - self.convert_csv_to_xlsx(imput_csv=arquivo_csv, output_excel=arquivo_excel) - - def __repr__(self): - # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance - # Devo substituir 'self.__class__.static_var' por 'type(self).static_var' ? - return f'{type(self).__name__}(file_path={self.file_path!r}, encoding={self.encoding!r}, efd_tipo={self.efd_tipo!r}, verbose={self.verbose!r})' - - def formatar_valor(self,nome,val): - """ - Evitar n repetições de 'if condicao_j then A_j else B_j' tal que 1 <= j <= n, - usar dicionário: myDict[key] = funtion_key(value) - Better optimization technique using if/else or dictionary - A series of if/else statement which receives the 'string' returns the appropriate function for it. - A dictionary maintaining the key-value pair. key as strings, and values as the function objects, - and one main function to search and return the function object. - """ - # https://stackoverflow.com/questions/11445226/better-optimization-technique-using-if-else-or-dictionary - # https://softwareengineering.stackexchange.com/questions/182093/why-store-a-function-inside-a-python-dictionary/182095 - # https://stackoverflow.com/questions/9168340/using-a-dictionary-to-select-function-to-execute - try: - # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance - # val_formated = self.__class__.myDict[nome](val) - val_formated = self.myDict[nome](val) - except: - val_formated = val - #print(f'nome = {nome} ; val = {val} ; val_formated = {val_formated}') - return val_formated - - # https://radek.io/2011/07/21/static-variables-and-methods-in-python/ - @staticmethod - def natureza_da_bc_dos_creditos(cfop): - """ - http://sped.rfb.gov.br/arquivo/show/1681 - Tabela CFOP - Operações Geradoras de Créditos - Versão 1.0.0 - """ - natureza_bc = None - - # Código 01 - CFOP de 'Aquisição de Bens para Revenda' - if cfop in ['1102','1113','1117','1118','1121','1251','1403','1652','2102','2113', - '2117','2118','2121','2251','2403','2652','3102','3251','3652']: - natureza_bc = 1 - # Código 02 - CFOP de 'Aquisição de Bens Utilizados como Insumo' - elif cfop in ['1101','1111','1116','1120','1122','1126','1128','1401','1407','1556', - '1651','1653','2101','2111','2116','2120','2122','2126','2128','2401', - '2407','2556','2651','2653','3101','3126','3128','3556','3651','3653']: - natureza_bc = 2 - # Código 03 - CFOP de 'Aquisição de Serviços Utilizados como Insumos' - elif cfop in ['1124','1125','1933','2124','2125','2933']: - natureza_bc = 3 - # Código 12 - CFOP de 'Devolução de Vendas Sujeitas à Incidência Não-Cumulativa' - elif cfop in ['1201','1202','1203','1204','1410','1411','1660','1661','1662','2201', - '2202','2410','2411','2660','2661','2662']: - natureza_bc = 12 - # Código 13 - CFOP de 'Outras Operações com Direito a Crédito' - elif cfop in ['1922','2922']: - natureza_bc = 13 - - return natureza_bc - - # https://stackoverflow.com/questions/25577578/access-class-variable-from-instance - def cadastro_do_participante(self,sped_efd): - """ - Registro 0150: Tabela de Cadastro do Participante - Retorno desta função: - info_do_participante[codigo_do_participante][campo] = descricao - """ - blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. - info = {} - for registro in blocoZero.registros: - REG = registro.valores[1] - if REG != '0150': - continue - codigo_do_participante = None - for campo in registro.campos: - valor = registro.valores[campo.indice] - # Fazer distinção entre 'NOME' do Registro0000 e 'NOME' do Registro0150 - nome = campo.nome + '_participante' - if campo.nome == 'COD_PART': - codigo_do_participante = valor - info[codigo_do_participante] = {} - if nome in type(self).registros_de_cadastro_do_participante and codigo_do_participante is not None: - info[codigo_do_participante][nome] = valor - return info - - def identificacao_do_item(self,sped_efd): - """ - Registro 0200: Tabela de Identificação do Item (Produtos e Serviços) - Retorno desta função: - info_do_item[codigo_do_item][campo] = descricao - """ - blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. - info = {} - for registro in blocoZero.registros: - REG = registro.valores[1] - if REG != '0200': - continue - codigo_do_item = None - for campo in registro.campos: - valor = registro.valores[campo.indice] - if campo.nome == 'COD_ITEM': - codigo_do_item = valor - info[codigo_do_item] = {} - if campo.nome in type(self).registros_de_identificacao_do_item and codigo_do_item is not None: - info[codigo_do_item][campo.nome] = valor - return info - - def plano_de_contas_contabeis(self,sped_efd): - """ - Registro 0500: Plano de Contas Contábeis - Retorno desta função: - info_do_item[codigo_do_item][campo] = descricao - """ - blocoZero = sped_efd._blocos['0'] # Ler apenas o bloco 0. - info = {} - for registro in blocoZero.registros: - REG = registro.valores[1] - if REG != '0500': - continue - codigo_do_item = None - for campo in registro.campos: - valor = registro.valores[campo.indice] - if campo.nome == 'COD_CTA': - codigo_do_item = valor - info[codigo_do_item] = {} - for campo in registro.campos: - valor = registro.valores[campo.indice] - if campo.nome in type(self).registros_de_plano_de_contas and codigo_do_item is not None: - info[codigo_do_item][campo.nome] = valor - return info - - - def obter_info_de_abertura(self,sped_efd): - registro = sped_efd._registro_abertura - REG = registro.valores[1] - nivel = registro.nivel - - # Utilizar uma combinação de valores para identificar univocamente um item. - combinacao = 'registro de abertura' - - info_de_abertura = {} - - # https://www.geeksforgeeks.org/python-creating-multidimensional-dictionary/ - info_de_abertura.setdefault(nivel, {}).setdefault(combinacao, {})['Nível Hierárquico'] = nivel - - if self.verbose: - print(f'registro.as_line() = {registro.as_line()} ; REG = {REG} ; nivel = {nivel}') - print(f'info_de_abertura = {info_de_abertura}\n') - - for campo in registro.campos: - - valor = registro.valores[campo.indice] - - if campo.nome in type(self).colunas_selecionadas: - info_de_abertura[nivel][combinacao][campo.nome] = valor - if campo.nome == 'DT_INI': - ddmmaaaa = registro.valores[campo.indice] - info_de_abertura[nivel][combinacao]['Data de Emissão'] = valor - info_de_abertura[nivel][combinacao]['Mês do Período de Apuração'] = ddmmaaaa[2:4] - info_de_abertura[nivel][combinacao]['Ano do Período de Apuração'] = ddmmaaaa[4:8] - if campo.nome == 'DT_FIN': - info_de_abertura[nivel][combinacao]['Data de Execução'] = valor - if self.verbose: - valor_formatado = self.formatar_valor(nome=campo.nome, val=valor) - print(f'campo.indice = {campo.indice:>2} ; campo.nome = {campo.nome:>22} ; registro.valores[{campo.indice:>2}] = {valor:<50} ; valor_formatado = {valor_formatado}') - - if self.verbose: - print(f'\ninfo_de_abertura = {info_de_abertura}\n') - - return info_de_abertura - - def adicionar_informacoes(self,dict_info): - """ - Adicionar informações em dict_info - Formatar alguns de seus campos com o uso de tabelas ou funções - """ - dict_info['Arquivo da SPED EFD'] = self.basename - dict_info['Linhas'] = next(type(self).contador_de_linhas) - - # re.search: find something anywhere in the string and return a match object. - if 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS']): - cst = int(dict_info['CST_PIS_COFINS']) - if 1 <= cst <= 49: - dict_info['Tipo de Operação'] = 'Saída' - elif 50 <= cst <= 99: - dict_info['Tipo de Operação'] = 'Entrada' - - # adicionar informação de NAT_BC_CRED para os créditos (50 <= cst <= 66) - # quando houver informação do CFOP e NAT_BC_CRED estiver vazio. - if ('CFOP' in dict_info and 'NAT_BC_CRED' in dict_info - and re.search(r'\d{4}', dict_info['CFOP']) and len(dict_info['NAT_BC_CRED']) == 0 - #and ( re.search(r'[1-9]', dict_info['ALIQ_PIS']) or re.search(r'[1-9]', dict_info['ALIQ_COFINS']) ) # aliq_cofins > 0 - and 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS'])): - cfop = str(dict_info['CFOP']) - cst = int(dict_info['CST_PIS_COFINS']) - if 50 <= cst <= 66: - dict_info['NAT_BC_CRED'] = type(self).natureza_da_bc_dos_creditos(cfop) - - # Índice de Origem do Crédito: Leia os comentários do 'Registro M100: Crédito de PIS/Pasep Relativo ao Período'. - # Os códigos vinculados à importação (108, 208 e 308) são obtidos através da informação de CFOP - # iniciado em 3 (quando existente) ou pelo campo IND_ORIG_CRED nos demais casos. - indicador_de_origem = 'Mercado Interno' # Default Value: 0 - Mercado Interno ; 1 - Mercado Externo (Importação). - if (('CFOP' in dict_info and re.search(r'^3\d{3}', dict_info['CFOP'])) or - ('IND_ORIG_CRED' in dict_info and dict_info['IND_ORIG_CRED'] == '1')): - indicador_de_origem = 'Mercado Externo (Importação)' - dict_info['IND_ORIG_CRED'] = indicador_de_origem - - # adicionar informação de cadastro do participante obtido do Registro 0150 - # info_do_participante[codigo_do_participante][campo] = descricao - if 'COD_PART' in dict_info and dict_info['COD_PART'] in self.info_do_participante: - codigo_do_participante = dict_info['COD_PART'] - for campo in self.info_do_participante[codigo_do_participante]: - dict_info[campo] = self.info_do_participante[codigo_do_participante][campo] - - # adicionar informação de identificação do item obtido do Registro 0200 - # info_do_item[codigo_do_item][campo] = descricao - if 'COD_ITEM' in dict_info and dict_info['COD_ITEM'] in self.info_do_item: - codigo_do_item = dict_info['COD_ITEM'] - for campo in self.info_do_item[codigo_do_item]: - dict_info[campo] = self.info_do_item[codigo_do_item][campo] - - # adicionar informação do plano de contas obtido do Registro 0500 - # info_da_conta[codigo_da_conta][campo] = descricao - if 'COD_CTA' in dict_info and dict_info['COD_CTA'] in self.info_da_conta: - codigo_da_conta = dict_info['COD_CTA'] - for campo in self.info_da_conta[codigo_da_conta]: - val = str(self.info_da_conta[codigo_da_conta][campo]) - if campo == 'COD_NAT_CC' and re.search(r'\d{1,2}', val): - val = val.zfill(2) # val = f'{int(val):02d}' - val = val + ' - ' + EFD_Tabelas.tabela_natureza_da_conta[val] - dict_info[campo] = val - - # Ao final, formatar alguns valores dos campos - for campo in dict_info.copy(): - valor_formatado = self.formatar_valor(nome=campo, val=dict_info[campo]) - dict_info[campo] = valor_formatado - - return dict_info - - def imprimir_informacoes_da_efd(self,sped_efd,output_filename): - - my_regex = r'^[A-K]' # Ler os blocos da A a K. - - campos_necessarios = ['CST_PIS', 'CST_COFINS', 'VL_BC_PIS', 'VL_BC_COFINS'] - # Bastam os seguintes campos, desde que os registros de PIS/PASEP ocorram sempre anteriores aos registros de COFINS: - # campos_necessarios = ['CST_COFINS', 'VL_BC_COFINS'] - - if self.efd_tipo == 'efd_icms_ipi': - campos_necessarios = ['CST_ICMS', 'VL_BC_ICMS'] - - # https://docs.python.org/3/library/csv.html - with open(output_filename, 'w', newline='', encoding='utf-8', errors='ignore') as csvfile: - - writer = csv.writer(csvfile, delimiter=';') - writer.writerow(type(self).colunas_selecionadas) # imprimir nomes das colunas apenas uma vez - - for key in sped_efd._blocos.keys(): - - match_bloco = re.search(my_regex, key, flags=re.IGNORECASE) - if not match_bloco: - continue - - bloco = sped_efd._blocos[key] - count = 1 - - info = self.info_de_abertura - - for registro in bloco.registros: - - REG = registro.valores[1] - - try: - nivel_anterior = nivel - num_de_campos_anterior = num_de_campos - except: - nivel_anterior = registro.nivel + 1 - num_de_campos_anterior = len(registro.campos) + 1 - - nivel = registro.nivel # nível atual - num_de_campos = len(registro.campos) - - cst_pis = '' # 2 caracteres - cst_cofins = '' # 2 caracteres - cst_icms = '' # 3 caracteres - cfop = 'cfop' # 4 caracteres - valor_item = 'valor_item' - - for campo in registro.campos: - if campo.nome == 'CST_PIS': - cst_pis = registro.valores[campo.indice] - if campo.nome == 'CST_COFINS': - cst_cofins = registro.valores[campo.indice] - if campo.nome == 'CST_ICMS': - cst_icms = registro.valores[campo.indice] - if campo.nome == 'CFOP': - cfop = registro.valores[campo.indice] - if campo.nome in type(self).registros_de_valor: - valor_item = registro.valores[campo.indice] - - cst_contribuicao = max(cst_pis,cst_cofins) - - # Utilizar uma combinação de valores para identificar univocamente um item. - combinacao = f'{cst_contribuicao}_{cst_icms}_{cfop}_{valor_item}' - - if self.verbose: - print(f'\ncount = {count:>2} ; key = {key} ; REG = {REG} ; nivel_anterior = {nivel_anterior} ; nivel = {nivel} ; ', end='') - print(f'num_de_campos_anterior = {num_de_campos_anterior} ; num_de_campos = {num_de_campos} ; ', end='') - print(f'cst_pis = {cst_pis} ; cst_cofins = {cst_cofins} ; cst_contribuicao = {cst_contribuicao}') - print(f'registro.as_line() = {registro.as_line()}') - - # As informações do pai e respectivos filhos devem ser apagadas quando - # o nivel hierárquico regride dos filhos para pais diferentes. - if nivel < nivel_anterior or (nivel == nivel_anterior and num_de_campos < num_de_campos_anterior): - if self.verbose: - if nivel < nivel_anterior: - print(f'\n nivel atual: nivel = {nivel} < nivel_anterior = {nivel_anterior} ; ', end='') - if nivel == nivel_anterior and num_de_campos < num_de_campos_anterior: - print(f'\n numero de campos atual: num_de_campos = {num_de_campos} < num_de_campos_anterior = {num_de_campos_anterior} ; ', end='') - print(f'deletar informações em info a partir do nível {nivel} em diante:') - - # Delete items from dictionary while iterating: - # https://www.geeksforgeeks.org/python-delete-items-from-dictionary-while-iterating/ - for nv in list(info): - if nv >= nivel: - del info[nv] - if self.verbose: - print(f'\t *** deletar informações do nível {nv}: del info[{nv}] ***') - print() if self.verbose else 0 - - # https://www.geeksforgeeks.org/python-creating-multidimensional-dictionary/ - info.setdefault(nivel, {}).setdefault(combinacao, {})['Nível Hierárquico'] = nivel - info[nivel][combinacao]['Valor do Item'] = valor_item - info[nivel][combinacao]['CST_PIS_COFINS'] = cst_contribuicao - - for campo in registro.campos: - - try: - valor = registro.valores[campo.indice] - except: - valor = f'{REG}[{campo.indice}:{campo.nome}] sem valor definido' - - if self.verbose: - valor_formatado = self.formatar_valor(nome=campo.nome, val=valor) - print(f'campo.indice = {campo.indice:>2} ; campo.nome = {campo.nome:>22} ; registro.valores[{campo.indice:>2}] = {valor:<50} ; valor_formatado = {valor_formatado}') - - if campo.nome not in type(self).registros_totais: # filtrar registros_totais - continue - - # reter em info{} as informações dos registros contidos em registros_totais - info[nivel][combinacao][campo.nome] = valor - - # Informar os campos em registros_de_data_emissao na coluna 'Data de Emissão'. - if campo.nome in type(self).registros_de_data_emissao: - info[nivel][combinacao]['Data de Emissão'] = valor - # Informar os campos em registros_de_data_execucao na coluna 'Data de Execução'. - if campo.nome in type(self).registros_de_data_execucao: - info[nivel][combinacao]['Data de Execução'] = valor - # Informar os campos de chave eletrônica de 44 dígitos na coluna 'Chave Eletrônica'. - if campo.nome in type(self).registros_de_chave_eletronica: - info[nivel][combinacao]['Chave Eletrônica'] = valor - - if self.verbose: - print(f'\n-->info[nivel][combinacao] = info[{nivel}][{combinacao}] = {info[nivel][combinacao]}\n') - - #https://stackoverflow.com/questions/3931541/how-to-check-if-all-of-the-following-items-are-in-a-list - # set(['a', 'c']).issubset(['a', 'b', 'c', 'd']) or set(lista1).issubset(lista2) - - if set(campos_necessarios).issubset( info[nivel][combinacao] ): - - # import this: Zen of Python: Flat is better than nested. - flattened_info = {} # eliminar os dois niveis [nivel][combinacao] e trazer todas as informações para apenas uma dimensão. - seen_column = set() # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? - - # em info{} há os registros_totais, em flattened_info{} apenas as colunas para impressao - for coluna in type(self).colunas_selecionadas: - flattened_info[coluna] = '' # atribuir valor inicial para todas as colunas - - if coluna in info[nivel][combinacao]: - flattened_info[coluna] = info[nivel][combinacao][coluna] # eliminar os dois niveis [nivel][combinacao] - seen_column.add(coluna) - if self.verbose: - print(f'nivel = {nivel:<10} ; combinacao = {combinacao:25} ; coluna = {coluna:>35} = {info[nivel][combinacao][coluna]:<35} ; info[nivel][combinacao] = {info[nivel][combinacao]}') - continue - - for nv in sorted(info,reverse=True): # nível em ordem decrescente - if coluna in seen_column: # informações já obtidas - break # as informações obtidas do nível mais alto prevalecerá - for comb in info[nv]: - if coluna in info[nv][comb]: - flattened_info[coluna] = info[nv][comb][coluna] # eliminar os dois niveis [nivel][combinacao] - seen_column.add(coluna) - if self.verbose: - print(f'nivel = {nivel} ; nv = {nv} ; combinacao = {comb:25} ; coluna = {coluna:>35} = {info[nv][comb][coluna]:<35} ; info[nivel][combinacao] = {info[nv][comb]}') - - print() if self.verbose else 0 - - flattened_info['Nº da Linha da EFD'] = registro.numero_da_linha - - # Adicionar informações em flattened_info ou formatar alguns de seus campos com o uso de tabelas ou funções - flattened_info = self.adicionar_informacoes(flattened_info) - - writer.writerow( flattened_info.values() ) - - # Se verbose == True, limitar tamanho do arquivo impresso - # Imprimir apenas os 20 primeiros registros de cada Bloco - count += 1 - if self.verbose and count > 20: - break - - print(f"Gerado o arquivo csv: '{output_filename}'.") - - - def convert_csv_to_xlsx(self, imput_csv, output_excel): - - # Create an new Excel file and add a worksheet. - workbook = xlsxwriter.Workbook(output_excel) - worksheet = workbook.add_worksheet('Itens de Docs Fiscais') - workbook.set_properties({'comments': 'Created with Python and XlsxWriter'}) - - # definindo a altura da primeira coluna, row_index == 0 - worksheet.set_row(0, 30) - - # Freeze pane on the top row. - worksheet.freeze_panes(1, 0) - - # Set up some formatting - header_format = workbook.add_format({ - 'align':'center', 'valign':'vcenter', - 'bg_color':'#C5D9F1', 'text_wrap':True, - 'font_size':10}) - - select_value = My_Switch(type(self).registros_totais,verbose=self.verbose) - select_value.formatar_valores_das_colunas() - myValue = select_value.dicionario - - select_format = My_Switch(type(self).registros_totais,verbose=self.verbose) - select_format.formatar_colunas_do_arquivo_excel(workbook) - myFormat = select_format.dicionario - - # First we find the length of the header column - largura_max = [len(c) for c in type(self).colunas_selecionadas] - - with open(imput_csv, 'r', encoding='utf-8', errors='ignore') as file: - - reader = csv.reader(file, delimiter=';') - for row_index, row in enumerate(reader): - - # nomes das colunas - if row_index == 0: - worksheet.write_row(row_index, 0, tuple(type(self).colunas_selecionadas), header_format) - continue - - for column_index, cell in enumerate(row): - - # reter largura máxima - if len(cell) > largura_max[column_index]: - largura_max[column_index] = len(cell) - - column_name = type(self).colunas_selecionadas[column_index] - - if len(cell) > 0: - worksheet.write(row_index, column_index, myValue[column_name](cell), myFormat[column_name]) - else: - # Write cell with row/column notation. - worksheet.write(row_index, column_index, cell) - - # Ajustar largura das colunas com os valores máximos - largura_min = 4 - for i, width in enumerate(largura_max): - if width > 120: # largura máxima - width = 120 - worksheet.set_column(i, i, width + largura_min) - - # Set the autofilter( $first_row, $first_col, $last_row, $last_col ) - worksheet.autofilter(0, 0, 0, len(largura_max) - 1) - - workbook.close() - - print(f"Gerado o arquivo XLSX Excel: '{output_excel}'.") diff --git a/sped/relatorios/efd_read_dir.py b/sped/relatorios/efd_read_dir.py deleted file mode 100755 index b7b6079..0000000 --- a/sped/relatorios/efd_read_dir.py +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import re, os, glob, sys -import cchardet as chardet # pip3 install cchardet - -Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '06 de Fevereiro de 2020 (início: 15 de Dezembro de 2020)' - -# Versão mínima exigida: python 3.6.0 -python_version = sys.version_info -if python_version < (3,6,0): - print('versão mínima exigida do python é 3.6.0') - print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) - exit() - -# Python OOP: Atributos e Métodos (def, funções) -class ReadFiles: - """Retorna um dicionário com informações dos arquivos encontrados no diretório""" - recursive = True - current_dir = os.getcwd() - seen_file = set() # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? - - def __init__(self, root_path = None, extension = None, pattern = None): - if root_path is None: - self.root_path = self.current_dir - else: - self.root_path = root_path - if extension is None: - self.extension = '*' - else: - self.extension = extension.strip('.') - if pattern is None: - self.pattern = '.' - else: - self.pattern = pattern - self.informations = {} # instance attributes, dict - - def __repr__(self): - return f'{self.__class__.__name__}(root_path = {self.root_path!r}, extension = {self.extension!r}, pattern = {self.pattern!r})' - - def get_file_extension(self,file_path): - # https://stackoverflow.com/questions/541390/extracting-extension-from-filename-in-python - _, file_extension = os.path.splitext(file_path) - return file_extension - - def get_filename(self,file_path): - # https://stackoverflow.com/questions/541390/extracting-extension-from-filename-in-python - filename = os.path.basename(file_path) - return filename - - # https://stackoverflow.com/questions/9629179/python-counting-lines-in-a-huge-10gb-file-as-fast-as-possible - def count_number_of_lines(self,file_path): - lines = 0 - try: - with open(file_path, mode='r', encoding="utf-8", errors='ignore') as filename: - for _ in filename: - lines += 1 - except FileNotFoundError: - print('O Arquivo não existe!') - return f'{lines:,}'.replace(',','.') - - # https://stackoverflow.com/questions/436220/how-to-determine-the-encoding-of-text - # https://chardet.readthedocs.io/en/latest/usage.html - # https://github.com/PyYoshi/cChardet - # iconv -f WINDOWS-1252 -t UTF-8 filename.txt # iconv - convert text from one character encoding to another - def predict_encoding(self,file_path): - '''Predict a file's encoding using cchardet''' - # import cchardet as chardet - lines = [] - my_regex = rb"^\|9999\|\d+\|" # descartar informações após a linha que contém |9999| seguido por dígitos ; b'': binary mode - with open(file_path, mode='rb') as filename: # mode 'rb': open the file as binary data - for line in filename: - match_object = re.search(my_regex, line, flags=re.IGNORECASE) - if len(lines) > 2**8 or match_object: - #print(f'{file_path = } ; {line = }') - break - lines.append(line) - rawdata = b''.join(lines) - info = chardet.detect(rawdata) # {'encoding': 'UTF-8', 'confidence': 0.9900000095367432} - encoding = info['encoding'] - if encoding is None or not re.search('UTF-8', encoding, flags=re.IGNORECASE): - encoding = 'Latin-1' - return encoding - - @property - def find_all_files(self): - # https://www.mkyong.com/python/python-how-to-list-all-files-in-a-directory/ - # https://docs.python.org/3/library/glob.html - files = [f for f in glob.glob(self.root_path + '/' + f"**/*.{self.extension}", recursive = self.recursive)] - # How to use a variable inside a regular expression? - my_regex = f"{self.pattern}" # Literal String Interpolation, "f-strings". - for file_path in files: - # path.isfile: The easiest way to check if both a file exists and if it is a file. - # seen_file: Is there a more Pythonic way to prevent adding a duplicate to a list? - if not os.path.isfile(file_path) or file_path.casefold() in self.seen_file: - continue - match_pattern = re.search(my_regex, str(file_path), flags=re.IGNORECASE) - if match_pattern: - self.seen_file.add(file_path.casefold()) - self.informations.setdefault(file_path, {})['tipo'] = 'Arquivo' - return self.informations - - @property - def find_all_efd_contrib(self): - indice = 0 - # Calling one method from another within same class in Python - return self.find_all_efd(indice) - - @property - def find_all_efd_icmsipi(self): - indice = 1 - # Calling one method from another within same class in Python - return self.find_all_efd(indice) - - def find_all_efd(self,indice=0): - if not self.informations: # How do I check if a list/dict is empty? - self.find_all_files # Calling one method from another within same class in Python - regex_efd = ["PISCOFINS", "SPED-EFD"] - efd_type = ['EFD Contribuições', 'EFD ICMS_IPI'] - idx_nome = [8,6] - idx_data = [6,4] - idx_cnpj = [9,7] - for file_path in self.informations: - encode_info = None - if not re.search(regex_efd[indice], file_path, flags=re.IGNORECASE): - continue - # Ler apenas a primeira linha para obter encode_info - with open(file_path, mode='rb') as filename: # mode 'rb': open the file as binary data - for line in filename: - info = chardet.detect(line) # {'encoding': 'UTF-8', 'confidence': 0.9900000095367432} - encode_info = info['encoding'] - #print(f'{file_path = } ; {encode_info = } ; {info = }') - break - # Ler apenas a primeira linha para obter informações do registro de abertura '0000'. - with open(file_path, mode='r', encoding=encode_info, errors='ignore') as filename: # encoding='latin-1','UTF-8' - for line in filename: - campos = line.strip().split('|') - if len(campos) <= 10: - break - campo_registro = campos[1] # A primeira linha deve conter o registro '0000' - campo_nome = campos[ idx_nome[indice] ] - campo_data = campos[ idx_data[indice] ] - campo_cnpj = campos[ idx_cnpj[indice] ] # o campo CNPJ deve conter 14 dígitos - match_regi = re.search( '0000', campo_registro) - match_cnpj = re.search(r'(\D|^)\d{14}(\D|$)', campo_cnpj) - match_data = re.search(r'(\D|^)\d{8}(\D|$)', campo_data) - if match_regi and match_cnpj and match_data: - self.informations[file_path]['tipo'] = efd_type[indice] - self.informations[file_path]['NOME'] = campo_nome - self.informations[file_path]['CNPJ'] = "%s.%s.%s/%s-%s" % (campo_cnpj[0:2],campo_cnpj[2:5],campo_cnpj[5:8],campo_cnpj[8:12],campo_cnpj[12:14]) - self.informations[file_path]['DT_INI'] = "%s/%s/%s" % (campo_data[0:2],campo_data[2:4],campo_data[4:8]) - break - # Filter a Dictionary by values in Python using dict comprehension - return {key: value for (key, value) in sorted(self.informations.items()) if value['tipo'] == efd_type[indice]} - - def get_file_info(self,file_path): - self.informations[file_path]['extensão' ] = self.get_file_extension(file_path) - self.informations[file_path]['codificação' ] = self.predict_encoding(file_path) - self.informations[file_path]['número de linhas'] = self.count_number_of_lines(file_path) - return self.informations[file_path] - -from time import time, sleep - -def Total_Execution_Time(start,end=None): - ''' - How to format elapsed time from seconds to hours, minutes, seconds and milliseconds in Python? - https://stackoverflow.com/questions/27779677/how-to-format-elapsed-time-from-seconds-to-hours-minutes-seconds-and-milliseco - https://stackoverflow.com/questions/3620943/measuring-elapsed-time-with-the-time-module/46544199 - https://blog.softhints.com/python-test-performance-and-measure-time-elapsed-in-seconds/ - ''' - if end is None: - end = time() - hours, rem = divmod(end-start, 3600) - minutes, seconds = divmod(rem, 60) - return f"{int(hours):02d}h:{int(minutes):02d}m:{seconds:07.4f}s" - - -if __name__ == '__main__': - - start = time() - - #print(f'\n{ReadFiles.__dict__ = } \n') - - lista_de_arquivos0 = ReadFiles(root_path = '.') - lista_de_arquivos1 = ReadFiles(root_path = 'EFD Contribuicoes', extension = 'txt', pattern = 'PISCOFINS') - lista_de_arquivos2 = ReadFiles(root_path = 'EFD ICMS_IPI-ADM', extension = 'txt', pattern = 'SPED-EFD' ) - - arquivos_da_efd = [lista_de_arquivos0, lista_de_arquivos1, lista_de_arquivos2] - - for lista_de_arquivos in arquivos_da_efd: - print(f'\nlista_de_arquivos = {lista_de_arquivos}:\n') - - print(f'lista_de_arquivos.find_all_files = {lista_de_arquivos.find_all_files} ; len(lista_de_arquivos.informations) = {len(lista_de_arquivos.informations)}\n') - - # SPED EFD Contrib: - for index,file_path in enumerate(lista_de_arquivos.find_all_efd_contrib,1): - print( f"{index:>6}: {file_path} ; tipo = {lista_de_arquivos.informations[file_path]['tipo']}" ) - #continue - for attribute, value in lista_de_arquivos.get_file_info(file_path).items(): - print(f'{attribute:>30}: {value}') - - # SPED EFD ICMS_IPI: - for index,file_path in enumerate(lista_de_arquivos.find_all_efd_icmsipi,1): - print( f"{index:>6}: {file_path} ; tipo = {lista_de_arquivos.informations[file_path]['tipo']}" ) - #continue - for attribute, value in lista_de_arquivos.get_file_info(file_path).items(): - print(f'{attribute:>30}: {value}') - - end = time() - print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)} \n') - From bd8f3ee6de0a07267acfcaa23388bce95a3575f5 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 19:35:00 -0300 Subject: [PATCH 28/52] =?UTF-8?q?corre=C3=A7=C3=A3o=20de=20concord=C3=A2nc?= =?UTF-8?q?ia=20em=20mensagem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_relatorios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index cace835..bea5a13 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -78,7 +78,7 @@ def main(): indice_do_arquivo = 0 else: print(f"\tDiretório atual: '{dir_path}'.") - print(f"\tNão foi encontrado arquivos SPED EFD neste diretório.\n") + print(f"\tNenhum arquivo SPED EFD foi encontrado neste diretório.\n") exit() # arquivo SPED EFD From 41666c53d29d6c816596aad0a58e6a4c43426dc1 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 20:09:33 -0300 Subject: [PATCH 29/52] importar EFD_Tabelas --- sped/relatorios/switcher.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sped/relatorios/switcher.py b/sped/relatorios/switcher.py index 37528ee..5e817b2 100644 --- a/sped/relatorios/switcher.py +++ b/sped/relatorios/switcher.py @@ -5,6 +5,7 @@ import sys, re from datetime import datetime +from sped.relatorios.efd_tabelas import EFD_Tabelas from sped.campos import (CampoData, CampoCNPJ, CampoCPF, CampoNCM, CampoCPFouCNPJ, CampoChaveEletronica) From be0ea07398b12bf60cfad4ab27f9230c03d61449 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Sun, 1 Mar 2020 20:35:23 -0300 Subject: [PATCH 30/52] =?UTF-8?q?verificar=20se=20len(data)=20=3D=3D=208?= =?UTF-8?q?=20d=C3=ADgitos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/print_csv_file.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sped/relatorios/print_csv_file.py b/sped/relatorios/print_csv_file.py index 0e6fca7..c0a5f8b 100644 --- a/sped/relatorios/print_csv_file.py +++ b/sped/relatorios/print_csv_file.py @@ -513,10 +513,10 @@ def info_dos_blocos(self,sped_efd,output_filename): info[nivel][combinacao][campo.nome] = valor # Informar os campos em registros_de_data_emissao na coluna 'Data de Emissão'. - if campo.nome in type(self).registros_de_data_emissao: + if campo.nome in type(self).registros_de_data_emissao and len(valor) == 8: info[nivel][combinacao]['Data de Emissão'] = valor # Informar os campos em registros_de_data_execucao na coluna 'Data de Execução'. - if campo.nome in type(self).registros_de_data_execucao: + if campo.nome in type(self).registros_de_data_execucao and len(valor) == 8: info[nivel][combinacao]['Data de Execução'] = valor # Informar os campos de chave eletrônica de 44 dígitos na coluna 'Chave Eletrônica'. if campo.nome in type(self).registros_de_chave_eletronica: From d493836523af0981a8df5ba2efd1bc9c09ccecfe Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Mon, 2 Mar 2020 13:53:23 -0300 Subject: [PATCH 31/52] =?UTF-8?q?reintrodu=C3=A7=C3=A3o=20de=20coment?= =?UTF-8?q?=C3=A1rios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/blocos.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sped/blocos.py b/sped/blocos.py index 8da85c3..fc09c1c 100644 --- a/sped/blocos.py +++ b/sped/blocos.py @@ -6,6 +6,8 @@ class Bloco(object): def __init__(self, nome=''): self._nome = nome self._registros = [] + #self.registro_abertura = Registro() + #self.registro_encerramento = Registro() def __repr__(self): return '<%s.%s(%s)>' % (self.__class__.__module__, @@ -13,10 +15,12 @@ def __repr__(self): @property def abertura(self): + # Define o indicador de movimento ou dados return self.registro_abertura @property def encerramento(self): + # Define a quantidade de registros return self.registro_encerramento @property @@ -24,4 +28,5 @@ def registros(self): return [self.abertura] + self._registros + [self.encerramento] def add(self, registro): + # Não adiciona o registro de abertura e fechamento self._registros.append(registro) From 2985410391260fe2cfa973668375c114abef6926 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Mon, 2 Mar 2020 13:55:59 -0300 Subject: [PATCH 32/52] =?UTF-8?q?altera=C3=A7=C3=A3o=20do=20nome=20do=20m?= =?UTF-8?q?=C3=A9todo=20=20para=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/efd/icms_ipi/blocos.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sped/efd/icms_ipi/blocos.py b/sped/efd/icms_ipi/blocos.py index e755e61..1b244e0 100644 --- a/sped/efd/icms_ipi/blocos.py +++ b/sped/efd/icms_ipi/blocos.py @@ -31,8 +31,8 @@ class Bloco0(Bloco): registro_encerramento = Registro0990() @property - def fechamento(self): - registro = self.__class__.registro_encerramento() + def encerramento(self): + registro = self.__class__.registro_encerramento # Define a quantidade de registros registro[2] = len(self._registros) + 3 return registro @@ -110,8 +110,8 @@ class Bloco9(Bloco): registro_encerramento = Registro9990() @property - def fechamento(self): - registro = self.__class__.registro_encerramento() + def encerramento(self): + registro = self.__class__.registro_encerramento # Define a quantidade de registros registro[2] = len(self._registros) + 3 return registro From 815c55f29397b9d1f27467644ae9d89db266c99a Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Mon, 2 Mar 2020 13:56:10 -0300 Subject: [PATCH 33/52] =?UTF-8?q?altera=C3=A7=C3=A3o=20do=20nome=20do=20m?= =?UTF-8?q?=C3=A9todo=20=20para=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/efd/pis_cofins/blocos.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sped/efd/pis_cofins/blocos.py b/sped/efd/pis_cofins/blocos.py index 5be42b7..2a54c89 100644 --- a/sped/efd/pis_cofins/blocos.py +++ b/sped/efd/pis_cofins/blocos.py @@ -30,6 +30,14 @@ class Bloco0(Bloco): registro_abertura = Registro0001() registro_encerramento = Registro0990() + @property + def encerramento(self): + registro = self.__class__.registro_encerramento + # Define a quantidade de registros + registro[2] = len(self._registros) + 3 + return registro + + class BlocoA(Bloco): """ Documentos Fiscais - Serviços (ISS) @@ -37,6 +45,7 @@ class BlocoA(Bloco): registro_abertura = RegistroA001() registro_encerramento = RegistroA990() + class BlocoC(Bloco): """ Documentos Fiscais I – Mercadorias (ICMS/IPI) @@ -99,3 +108,10 @@ class Bloco9(Bloco): """ registro_abertura = Registro9001() registro_encerramento = Registro9990() + + @property + def encerramento(self): + registro = self.__class__.registro_encerramento + # Define a quantidade de registros + registro[2] = len(self._registros) + 3 + return registro From 349fe39d2a025e831cd0a29737d9c7a776845ea5 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Mon, 2 Mar 2020 13:57:02 -0300 Subject: [PATCH 34/52] =?UTF-8?q?novos=20coment=C3=A1rios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_relatorios.py | 4 ++-- sped/relatorios/switcher.py | 4 ++++ test/pis_cofins.py | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index bea5a13..5c102e6 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -91,12 +91,12 @@ def main(): arquivo_excel = filename + '.xlsx' print(f"\nSelecionado o arquivo {indice_do_arquivo + 1}: '{file_path}'.\n") - input("Tecle Enter para gerar arquivo Excel .xlsx com informações da SPED EFD.") + input("Tecle para gerar arquivo Excel .xlsx com informações da SPED EFD: ") print() start = time() - csv_file = SPED_EFD_Info(file_path, encoding=codificacao, efd_tipo = tipo_da_efd, verbose=False) + csv_file = SPED_EFD_Info(file_path, encoding=codificacao, efd_tipo=tipo_da_efd, verbose=False) csv_file.imprimir_arquivo_csv diff --git a/sped/relatorios/switcher.py b/sped/relatorios/switcher.py index 5e817b2..5097267 100644 --- a/sped/relatorios/switcher.py +++ b/sped/relatorios/switcher.py @@ -218,3 +218,7 @@ def formatar_colunas_do_arquivo_excel(self,workbook): # Caso não ocorra nenhum match, retornar default value = format_default self.dicionario[nome_da_coluna] = switcher.get(True, format_default) + + if self.verbose: + for idx, key in enumerate(sorted(self.dicionario.keys()),1): + print(f'{key:>40}: [{idx:>2}] {self.dicionario[key]}') diff --git a/test/pis_cofins.py b/test/pis_cofins.py index fe2e27a..8b16e2d 100644 --- a/test/pis_cofins.py +++ b/test/pis_cofins.py @@ -10,6 +10,11 @@ sys.path.insert(0, os.path.dirname(test_root)) sys.path.insert(0, test_root) +# De fato, trata-se de um teste de registro da EFD ICMS_IPI +# Não se trata de teste de EFD PIS_COFINS +#from sped.efd.pis_cofins.arquivos import ArquivoDigital +#from sped.efd.pis_cofins.registros import Registro0100 + from sped.efd.icms_ipi.arquivos import ArquivoDigital from sped.efd.icms_ipi.registros import Registro0100 From dd5dc5886a77b790b87fec248dbfc214591816e3 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 02:42:28 -0300 Subject: [PATCH 35/52] possibilidade de selecionar multiplos arquivos --- sped/relatorios/convert_csv_to_xlsx.py | 2 +- sped/relatorios/efd_relatorios.py | 156 ++++++++++++++++--------- 2 files changed, 101 insertions(+), 57 deletions(-) diff --git a/sped/relatorios/convert_csv_to_xlsx.py b/sped/relatorios/convert_csv_to_xlsx.py index 2ed1af6..b031b0f 100644 --- a/sped/relatorios/convert_csv_to_xlsx.py +++ b/sped/relatorios/convert_csv_to_xlsx.py @@ -95,4 +95,4 @@ def convert_csv_to_xlsx(self): workbook.close() - print(f"Gerado arquivo Excel .xlsx: '{self.output_excel}'.") + print(f"Gerado arquivo Excel: '{self.output_excel}'.") diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 5c102e6..390238f 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -2,34 +2,24 @@ # -*- coding: utf-8 -*- Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '01 de Março de 2020 (início: 29 de Janeiro de 2020)' +Data = '03 de Março de 2020 (início: 29 de Janeiro de 2020)' +Home = 'https://github.com/claudiofsr/python-sped' # Instruções (no Linux): -# Digite em seu web brawser o endereço abaixo: +# Para obter uma cópia, na linha de comando, execute: +# > git clone git@github.com:claudiofsr/python-sped.git -# Escolha a opção A ou B: -# A: https://github.com/claudiofsr -# Selecione o projeto 'python-sped'. -# Em seguida selecione o Branch 'relatorios'. -# B: https://github.com/claudiofsr/python-sped/tree/relatorios - -# Execute os passos 1 ou 2: -# 1. Na linha de comando execute: -# > git clone -b relatorios git@github.com:claudiofsr/python-sped.git # Em seguida, vá ao diretório python-sped: # > cd python-sped -# 2. Em 'Clone ou download' clique em 'Download ZIP': -# Em seguida, descompacte o arquivo copiado: -# > unzip python-sped-relatorios.zip -# > cd python-sped-relatorios # Para instalar o módulo do SPED em seu sistema execute, como superusuário: # > python setup.py install -# Em um diretório que contenha arquivos de EFD Contribuições, + +# Em um diretório que contenha arquivos de SPED EFD, # execute no terminal o camando: # > efd_relatorios -import sys, os +import sys, os, re from time import time, sleep from sped import __version__ from sped.relatorios.find_efd_files import ReadFiles, Total_Execution_Time @@ -45,7 +35,7 @@ def main(): - print(f'\n\tPython Sped - versão: {__version__}\n') + print(f'\n Python Sped - versão: {__version__}\n') dir_path = os.getcwd() # CurrentDirectory extensao = 'txt' @@ -56,59 +46,113 @@ def main(): arquivos_efd_icms_ipi = list(lista_de_arquivos.find_all_efd_icmsipi) # SPED EFD ICMS_IPI arquivos_sped_efd = arquivos_efd_contrib + arquivos_efd_icms_ipi + + if len(arquivos_sped_efd) == 0: + print(f"\tDiretório atual: '{dir_path}'.") + print(f"\tNenhum arquivo SPED EFD foi encontrado neste diretório.\n") + exit() + + print(" Arquivo(s) de SPED EFD encontrado(s) neste diretório:\n") for index,file_path in enumerate(arquivos_sped_efd,1): print( f"{index:>6}: {file_path}") for attribute, value in lista_de_arquivos.get_file_info(file_path).items(): print(f'{attribute:>25}: {value}') + + # argumentos: sys.argv: argv[0], argv[1], argv[2], ... + command_line = sys.argv[1:] - indice_do_arquivo = None - - if len(arquivos_sped_efd) > 1: - while indice_do_arquivo is None: - my_input = input(f"\nFavor, digite o número do arquivo SPED EFD (1 a {len(arquivos_sped_efd)}): ") - try: - my_input = int(my_input) - if 1 <= my_input <= len(arquivos_sped_efd): - indice_do_arquivo = my_input - 1 - except: - print(f"-->Opção incorreta: '{my_input}'.") - print(f"-->Digite um número inteiro entre 1 e {len(arquivos_sped_efd)}.") - elif len(arquivos_sped_efd) == 1: - indice_do_arquivo = 0 - else: - print(f"\tDiretório atual: '{dir_path}'.") - print(f"\tNenhum arquivo SPED EFD foi encontrado neste diretório.\n") + if len(command_line) == 0: + print("\n Selecione os arquivos pelos números correspondentes.") + print(" Use dois pontos .. para indicar intervalo.") + print(" Modos de uso:\n") + print("\tExemplo A (selecionar apenas o arquivo 4): \n\tefd_relatorios 4 \n") + print("\tExemplo B (selecionar os arquivos de 1 a 6): \n\tefd_relatorios 1 2 3 4 5 6 \n") + print("\tExemplo C (selecionar os arquivos de 1 a 6): \n\tefd_relatorios 1..6 \n") + print("\tExemplo D (selecionar os arquivos 2, 4 e 8): \n\tefd_relatorios 2 4 8 \n") + print("\tExemplo E (selecionar os arquivos de 1 a 5, 7, 9, 12 a 15 e 18): \n\tefd_relatorios 1..5 7 9 12..15 18 \n") exit() - - # arquivo SPED EFD - file_path = arquivos_sped_efd[indice_do_arquivo] - tipo_da_efd = lista_de_arquivos.informations[file_path]['tipo'] - codificacao = lista_de_arquivos.informations[file_path]['codificação'] - - filename = os.path.splitext(file_path)[0] # ('./efd_info', '.py') - arquivo_csv = filename + '.csv' - arquivo_excel = filename + '.xlsx' + else: + # concatenate item in list to strings + opcoes = ' '.join(command_line) + # remover todos os caracteres, exceto dígitos, pontos e espaços em branco + opcoes = re.sub(r'[^\d\.\s]', '', opcoes) + # substituir dois ou mais espaços em branco por apenas um. + opcoes = re.sub(r'\s{2,}', ' ', opcoes) + # remover os possíveis espaços em branco do início e do final da variável + opcoes = opcoes.strip() + # remover possíveis espaços: '32 .. 41' --> '32..41' ou também '32... .. 41' --> '32..41' + opcoes = re.sub(r'(?<=\d)[\.\s]*\.[\.\s]*(?=\d)', '..', opcoes) + # string.split(separator, maxsplit): maxsplit -1 split "all occurrences" + # command_line = opcoes.split(r' ', -1) + # split string based on regex + command_line = re.split(r'\s+', opcoes) - print(f"\nSelecionado o arquivo {indice_do_arquivo + 1}: '{file_path}'.\n") - input("Tecle para gerar arquivo Excel .xlsx com informações da SPED EFD: ") - print() + arquivos_escolhidos = [] + # print(f'\n{arquivos_sped_efd = } ; {len(arquivos_sped_efd) = } ; {command_line = }\n') + + for indice in command_line: # exemplo: ('5', '17', '32..41') + + apenas_um_digito = re.search(r'^(\d+)$', indice) + intervalo_digito = re.search(r'^(\d+)\.{2}(\d+)$', indice) + + if apenas_um_digito: # exemplo: '17' + value_1 = int(apenas_um_digito.group(1)) # group(1) will return the 1st capture. + if value_1 > len(arquivos_sped_efd) or value_1 <= 0: + print(f"\nArquivo número {value_1} não encontrado!\n") + exit() + sped_file = arquivos_sped_efd[value_1 - 1] + # evitar repetição e manter a mesma ordem + if sped_file not in arquivos_escolhidos: + arquivos_escolhidos.append(sped_file) + elif intervalo_digito: # exemplo: '32..41' + value_1 = int(intervalo_digito.group(1)) + value_2 = int(intervalo_digito.group(2)) + if value_1 > len(arquivos_sped_efd) or value_1 <= 0: + print(f"\nArquivo número {value_1} não encontrado!\n") + exit() + if value_2 > len(arquivos_sped_efd) or value_2 <= 0: + print(f"\nArquivo número {value_2} não encontrado!\n") + exit() + if value_1 > value_2: + print(f"\n{value_1}..{value_2}: o primeiro número deve ser menor ou igual ao segundo!\n") + exit() + for index in range(value_1 - 1, value_2): + sped_file = arquivos_sped_efd[index] + # evitar repetição e manter a mesma ordem + if sped_file not in arquivos_escolhidos: + arquivos_escolhidos.append(sped_file) + else: + print(f"\nOpção {indice} inválida!\n") + exit() + print(f'\nArquivo(s) selecionado(s) {command_line}:') + for sped_file in arquivos_escolhidos: + print(f'\t{sped_file}') + print() + start = time() - - csv_file = SPED_EFD_Info(file_path, encoding=codificacao, efd_tipo=tipo_da_efd, verbose=False) - - csv_file.imprimir_arquivo_csv - excel_file = CSV_to_Excel(arquivo_csv, arquivo_excel, verbose=False) + for sped_file_path in arquivos_escolhidos: + + tipo_da_efd = lista_de_arquivos.informations[sped_file_path]['tipo'] + codificacao = lista_de_arquivos.informations[sped_file_path]['codificação'] - excel_file.convert_csv_to_xlsx + filename = os.path.splitext(sped_file_path)[0] # ('/home/user/file', '.txt') + arquivo_csv = filename + '.csv' + arquivo_excel = filename + '.xlsx' + + csv_file = SPED_EFD_Info(sped_file_path, encoding=codificacao, efd_tipo=tipo_da_efd, verbose=False) + csv_file.imprimir_arquivo_csv - if os.path.exists(arquivo_csv): - os.remove(arquivo_csv) + excel_file = CSV_to_Excel(arquivo_csv, arquivo_excel, verbose=False) + excel_file.convert_csv_to_xlsx + + if os.path.exists(arquivo_csv): + os.remove(arquivo_csv) end = time() - + print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)}\n') if __name__ == '__main__': From fb1a0244c5c42da2ba1c251a7574c49386a6cab1 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 09:54:53 -0300 Subject: [PATCH 36/52] =?UTF-8?q?adicionada=20a=20vari=C3=A1vel=20numero?= =?UTF-8?q?=5Fdo=5Farquivo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/convert_csv_to_xlsx.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sped/relatorios/convert_csv_to_xlsx.py b/sped/relatorios/convert_csv_to_xlsx.py index b031b0f..5f61191 100644 --- a/sped/relatorios/convert_csv_to_xlsx.py +++ b/sped/relatorios/convert_csv_to_xlsx.py @@ -23,9 +23,10 @@ class CSV_to_Excel: # initialize the attributes of the class - def __init__(self, arquivo_csv, arquivo_excel, verbose=False): + def __init__(self, arquivo_csv, arquivo_excel, numero_do_arquivo, verbose=False): self.imput_csv = arquivo_csv self.output_excel = arquivo_excel + self.numero_do_arquivo = numero_do_arquivo self.verbose = verbose @property @@ -95,4 +96,4 @@ def convert_csv_to_xlsx(self): workbook.close() - print(f"Gerado arquivo Excel: '{self.output_excel}'.") + print(f"finalizado arquivo {self.numero_do_arquivo:2d} -> '{self.output_excel}'.") From aecf6a036caa4f4e13ea0b7d792600abef53480d Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 09:56:01 -0300 Subject: [PATCH 37/52] =?UTF-8?q?implementado=20o=20processamento=20de=20m?= =?UTF-8?q?=C3=BAltiplos=20arquivos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_relatorios.py | 77 +++++++++++++++++++------------ 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 390238f..8561181 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -26,6 +26,11 @@ from sped.relatorios.print_csv_file import SPED_EFD_Info from sped.relatorios.convert_csv_to_xlsx import CSV_to_Excel +import psutil +from multiprocessing import Pool # take advantage of multiple cores + +num_cpus = psutil.cpu_count(logical=True) + # Versão mínima exigida: python 3.6.0 python_version = sys.version_info if python_version < (3,6,0): @@ -33,6 +38,26 @@ print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) exit() +def make_excel_file(sped_file_path, numero_do_arquivo, lista_de_arquivos): + + tipo_da_efd = lista_de_arquivos.informations[sped_file_path]['tipo'] + codificacao = lista_de_arquivos.informations[sped_file_path]['codificação'] + + filename = os.path.splitext(sped_file_path)[0] # ('/home/user/file', '.txt') + arquivo_csv = filename + '.csv' + arquivo_excel = filename + '.xlsx' + + csv_file = SPED_EFD_Info(sped_file_path, encoding=codificacao, efd_tipo=tipo_da_efd, verbose=False) + csv_file.imprimir_arquivo_csv + + excel_file = CSV_to_Excel(arquivo_csv, arquivo_excel, numero_do_arquivo, verbose=False) + excel_file.convert_csv_to_xlsx + + if os.path.exists(arquivo_csv): + os.remove(arquivo_csv) + + return 1 + def main(): print(f'\n Python Sped - versão: {__version__}\n') @@ -75,6 +100,7 @@ def main(): else: # concatenate item in list to strings opcoes = ' '.join(command_line) + comando_inicial = opcoes # remover todos os caracteres, exceto dígitos, pontos e espaços em branco opcoes = re.sub(r'[^\d\.\s]', '', opcoes) # substituir dois ou mais espaços em branco por apenas um. @@ -88,8 +114,7 @@ def main(): # split string based on regex command_line = re.split(r'\s+', opcoes) - arquivos_escolhidos = [] - # print(f'\n{arquivos_sped_efd = } ; {len(arquivos_sped_efd) = } ; {command_line = }\n') + arquivos_escolhidos = {} # usar dicionário para evitar repetição for indice in command_line: # exemplo: ('5', '17', '32..41') @@ -102,12 +127,11 @@ def main(): print(f"\nArquivo número {value_1} não encontrado!\n") exit() sped_file = arquivos_sped_efd[value_1 - 1] - # evitar repetição e manter a mesma ordem - if sped_file not in arquivos_escolhidos: - arquivos_escolhidos.append(sped_file) + arquivos_escolhidos[sped_file] = value_1 + elif intervalo_digito: # exemplo: '32..41' - value_1 = int(intervalo_digito.group(1)) - value_2 = int(intervalo_digito.group(2)) + value_1 = int(intervalo_digito.group(1)) # 32 + value_2 = int(intervalo_digito.group(2)) # 41 if value_1 > len(arquivos_sped_efd) or value_1 <= 0: print(f"\nArquivo número {value_1} não encontrado!\n") exit() @@ -119,41 +143,36 @@ def main(): exit() for index in range(value_1 - 1, value_2): sped_file = arquivos_sped_efd[index] - # evitar repetição e manter a mesma ordem - if sped_file not in arquivos_escolhidos: - arquivos_escolhidos.append(sped_file) + arquivos_escolhidos[sped_file] = index + 1 else: print(f"\nOpção {indice} inválida!\n") exit() - print(f'\nArquivo(s) selecionado(s) {command_line}:') + print(f"\nArquivo(s) selecionado(s) '{comando_inicial}' -> {list(arquivos_escolhidos.values())}:") for sped_file in arquivos_escolhidos: print(f'\t{sped_file}') print() start = time() - for sped_file_path in arquivos_escolhidos: - - tipo_da_efd = lista_de_arquivos.informations[sped_file_path]['tipo'] - codificacao = lista_de_arquivos.informations[sped_file_path]['codificação'] - - filename = os.path.splitext(sped_file_path)[0] # ('/home/user/file', '.txt') - arquivo_csv = filename + '.csv' - arquivo_excel = filename + '.xlsx' - - csv_file = SPED_EFD_Info(sped_file_path, encoding=codificacao, efd_tipo=tipo_da_efd, verbose=False) - csv_file.imprimir_arquivo_csv - - excel_file = CSV_to_Excel(arquivo_csv, arquivo_excel, verbose=False) - excel_file.convert_csv_to_xlsx - - if os.path.exists(arquivo_csv): - os.remove(arquivo_csv) + # https://sebastianraschka.com/Articles/2014_multiprocessing.html + # https://stackoverflow.com/questions/26068819/how-to-kill-all-pool-workers-in-multiprocess + # https://www.programcreek.com/python/index/175/multiprocessing + + pool = Pool( processes = int(num_cpus - 2) ) + results = [ pool.apply_async(make_excel_file, args=(k,v,lista_de_arquivos)) for (k,v) in arquivos_escolhidos.items() ] + output = [ p.get() for p in results ] # output = [1, 1, 1, 1, 1, 1] + pool.close() + + num_total_de_arquivos = sum(output) + if num_total_de_arquivos > 1: + print(f"\nForam gerados {num_total_de_arquivos} arquivos xlsx do Excel.\n") + else: + print(f"\nFoi gerado {num_total_de_arquivos} arquivo xlsx do Excel.\n") end = time() - print(f'\nTotal Execution Time: {Total_Execution_Time(start,end)}\n') + print(f'Total Execution Time: {Total_Execution_Time(start,end)}\n') if __name__ == '__main__': main() From 0c48529b1b95c284f87ec6219d93ba9a885ded2a Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 10:25:11 -0300 Subject: [PATCH 38/52] [FIX] considerado o caso num_cpus <= 2 --- sped/relatorios/efd_relatorios.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 8561181..59bbe82 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -148,7 +148,7 @@ def main(): print(f"\nOpção {indice} inválida!\n") exit() - print(f"\nArquivo(s) selecionado(s) '{comando_inicial}' -> {list(arquivos_escolhidos.values())}:") + print(f"\nArquivo(s) selecionado(s) '{comando_inicial}' -> {list(arquivos_escolhidos.values())}:\n") for sped_file in arquivos_escolhidos: print(f'\t{sped_file}') print() @@ -159,7 +159,7 @@ def main(): # https://stackoverflow.com/questions/26068819/how-to-kill-all-pool-workers-in-multiprocess # https://www.programcreek.com/python/index/175/multiprocessing - pool = Pool( processes = int(num_cpus - 2) ) + pool = Pool( processes = int(max(1, num_cpus - 2)) ) results = [ pool.apply_async(make_excel_file, args=(k,v,lista_de_arquivos)) for (k,v) in arquivos_escolhidos.items() ] output = [ p.get() for p in results ] # output = [1, 1, 1, 1, 1, 1] pool.close() From d4ffa40d55639acb59f04b07c3074699dff40239 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 15:23:04 -0300 Subject: [PATCH 39/52] =?UTF-8?q?remo=C3=A7=C3=A3o=20da=20vari=C3=A1vel=20?= =?UTF-8?q?numero=5Fdo=5Farquivo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/convert_csv_to_xlsx.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sped/relatorios/convert_csv_to_xlsx.py b/sped/relatorios/convert_csv_to_xlsx.py index 5f61191..0e941d3 100644 --- a/sped/relatorios/convert_csv_to_xlsx.py +++ b/sped/relatorios/convert_csv_to_xlsx.py @@ -23,10 +23,9 @@ class CSV_to_Excel: # initialize the attributes of the class - def __init__(self, arquivo_csv, arquivo_excel, numero_do_arquivo, verbose=False): + def __init__(self, arquivo_csv, arquivo_excel, verbose=False): self.imput_csv = arquivo_csv self.output_excel = arquivo_excel - self.numero_do_arquivo = numero_do_arquivo self.verbose = verbose @property @@ -95,5 +94,3 @@ def convert_csv_to_xlsx(self): worksheet.autofilter(0, 0, 0, len(largura_max) - 1) workbook.close() - - print(f"finalizado arquivo {self.numero_do_arquivo:2d} -> '{self.output_excel}'.") From fac4899f37262757c518f8a12549210be01e9ba4 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 15:24:58 -0300 Subject: [PATCH 40/52] imprimir csv sem adicionar os nomes da colunas --- sped/relatorios/print_csv_file.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sped/relatorios/print_csv_file.py b/sped/relatorios/print_csv_file.py index c0a5f8b..67847de 100644 --- a/sped/relatorios/print_csv_file.py +++ b/sped/relatorios/print_csv_file.py @@ -74,12 +74,10 @@ class SPED_EFD_Info: # initialize the attributes of the class - def __init__(self, file_path=None, encoding=None, efd_tipo=None, verbose=False): + def __init__(self, file_path, numero_do_arquivo, encoding=None, efd_tipo=None, verbose=False): - if file_path is None or not os.path.isfile(file_path): - raise ValueError(f'O arquivo file_path = {file_path} não é válido!') - else: - self.file_path = file_path + self.file_path = file_path + self.numero_do_arquivo = numero_do_arquivo if encoding is None: self.encoding = 'UTF-8' @@ -415,7 +413,7 @@ def info_dos_blocos(self,sped_efd,output_filename): with open(output_filename, 'w', newline='', encoding='utf-8', errors='ignore') as csvfile: writer = csv.writer(csvfile, delimiter=';') - writer.writerow(type(self).colunas_selecionadas) # imprimir nomes das colunas apenas uma vez + #writer.writerow(type(self).colunas_selecionadas) # imprimir nomes das colunas apenas uma vez for key in sped_efd._blocos.keys(): @@ -572,3 +570,5 @@ def info_dos_blocos(self,sped_efd,output_filename): count += 1 if self.verbose and count > 20: break + + print(f"finalizado arquivo {self.numero_do_arquivo:2d} -> '{output_filename}'.") From 5575c9b8aa83ae396eb7e68e565d2e0fe8476e80 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 15:26:34 -0300 Subject: [PATCH 41/52] unificar csv e imprimir um arquivo final xlsx --- sped/relatorios/efd_relatorios.py | 78 ++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 16 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 59bbe82..3419cb6 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -38,25 +38,18 @@ print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) exit() -def make_excel_file(sped_file_path, numero_do_arquivo, lista_de_arquivos): +def make_csv_file(sped_file_path, numero_do_arquivo, lista_de_arquivos): tipo_da_efd = lista_de_arquivos.informations[sped_file_path]['tipo'] codificacao = lista_de_arquivos.informations[sped_file_path]['codificação'] filename = os.path.splitext(sped_file_path)[0] # ('/home/user/file', '.txt') arquivo_csv = filename + '.csv' - arquivo_excel = filename + '.xlsx' - csv_file = SPED_EFD_Info(sped_file_path, encoding=codificacao, efd_tipo=tipo_da_efd, verbose=False) + csv_file = SPED_EFD_Info(sped_file_path, numero_do_arquivo, encoding=codificacao, efd_tipo=tipo_da_efd, verbose=False) csv_file.imprimir_arquivo_csv - excel_file = CSV_to_Excel(arquivo_csv, arquivo_excel, numero_do_arquivo, verbose=False) - excel_file.convert_csv_to_xlsx - - if os.path.exists(arquivo_csv): - os.remove(arquivo_csv) - - return 1 + return {numero_do_arquivo: arquivo_csv} def main(): @@ -158,17 +151,70 @@ def main(): # https://sebastianraschka.com/Articles/2014_multiprocessing.html # https://stackoverflow.com/questions/26068819/how-to-kill-all-pool-workers-in-multiprocess # https://www.programcreek.com/python/index/175/multiprocessing - pool = Pool( processes = int(max(1, num_cpus - 2)) ) - results = [ pool.apply_async(make_excel_file, args=(k,v,lista_de_arquivos)) for (k,v) in arquivos_escolhidos.items() ] - output = [ p.get() for p in results ] # output = [1, 1, 1, 1, 1, 1] + results = [ pool.apply_async(make_csv_file, args=(k,v,lista_de_arquivos)) for (k,v) in arquivos_escolhidos.items() ] + output = [ p.get() for p in results ] # output = [{num: csv_file_path}] pool.close() - num_total_de_arquivos = sum(output) + num_total_de_arquivos = len(output) if num_total_de_arquivos > 1: - print(f"\nForam gerados {num_total_de_arquivos} arquivos xlsx do Excel.\n") + print(f"\nForam gerados {num_total_de_arquivos} arquivos csv temporários.\n") else: - print(f"\nFoi gerado {num_total_de_arquivos} arquivo xlsx do Excel.\n") + print(f"\nFoi gerado {num_total_de_arquivos} arquivo csv temporário.\n") + + # https://stackoverflow.com/questions/5236296/how-to-convert-list-of-dict-to-dict + new_dict = { key: dicts[key] for dicts in output for key in dicts } # dict Comprehensions + #print(f'{new_dict = } ; {new_dict.values() = }') + + data_ini = {} + data_fim = {} + + for value in new_dict.values(): + # PISCOFINS_20150701_20150731_12345678912345_...csv + # 12345678912345-123456789123-20170101-20170131-1-...-SPED-EFD.csv + data01 = re.search(r'PISCOFINS_(\d{8})_(\d{8})', value, flags=re.IGNORECASE) + data02 = re.search(r'\d{14}.\d+.(\d{8}).(\d{8}).*SPED-EFD', value, flags=re.IGNORECASE) + + if data01: + data_ini[ data01.group(1) ] = 1 + data_fim[ data01.group(2) ] = 1 + if data02: + data_ini[ data02.group(1) ] = 1 + data_fim[ data02.group(2) ] = 1 + + #print(f'{data_ini = } ; {data_fim = }') + + if len(data_ini) >= 1: + ini = list(sorted(data_ini.keys()))[0] + if len(data_fim) >= 1: + fim = list(sorted(data_fim.keys()))[-1] + + target = f'Info do Contribuinte - SPED EFD - {ini} a {fim}' + + final_file_csv = target + ".csv" + final_file_excel = target + ".xlsx" + + # unificar todos os arquivos csv no arquivo final_file_csv + with open(final_file_csv, 'w', newline='', encoding='utf-8', errors='ignore') as csvfile: + # imprimir nomes das colunas apenas uma vez na primeira linha + nomes_das_colunas = ';'.join(SPED_EFD_Info.colunas_selecionadas) + csvfile.write( nomes_das_colunas + '\n' ) + + # https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files + for num,csv_file_path in sorted(new_dict.items()): + print(f"arquivo[{num:2d}]: '{csv_file_path}'.") + with open(csv_file_path, mode='r') as f: + csvfile.write(f.read()) # read all lines at once + if os.path.exists(csv_file_path): + os.remove(csv_file_path) + + excel_file = CSV_to_Excel(final_file_csv, final_file_excel, verbose=False) + excel_file.convert_csv_to_xlsx + + if os.path.exists(final_file_csv): + os.remove(final_file_csv) + + print(f"\nFinalmente, foi gerado o arquivo xlsx do Excel -> '{final_file_excel}'.\n") end = time() From 3adef0e6523e5212d51a2bd569ea87895ad8babc Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 15:35:38 -0300 Subject: [PATCH 42/52] =?UTF-8?q?altera=C3=A7=C3=A3o=20nas=20vari=C3=A1vei?= =?UTF-8?q?s=20ini=20e=20fim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_relatorios.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 3419cb6..ee5607b 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -184,10 +184,8 @@ def main(): #print(f'{data_ini = } ; {data_fim = }') - if len(data_ini) >= 1: - ini = list(sorted(data_ini.keys()))[0] - if len(data_fim) >= 1: - fim = list(sorted(data_fim.keys()))[-1] + ini = list(sorted(data_ini.keys()))[0] + fim = list(sorted(data_fim.keys()))[-1] target = f'Info do Contribuinte - SPED EFD - {ini} a {fim}' From 7f80f06b784fc8ace110bba1952d8931ed666843 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 17:42:04 -0300 Subject: [PATCH 43/52] open file with errors='ignore' --- sped/relatorios/efd_relatorios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index ee5607b..68aa8a3 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -201,7 +201,7 @@ def main(): # https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files for num,csv_file_path in sorted(new_dict.items()): print(f"arquivo[{num:2d}]: '{csv_file_path}'.") - with open(csv_file_path, mode='r') as f: + with open(csv_file_path, mode='r', encoding='utf-8', errors='ignore') as f: csvfile.write(f.read()) # read all lines at once if os.path.exists(csv_file_path): os.remove(csv_file_path) From 70c2a08ebdb3b0eb0788852cba46b64fb550b0a1 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Tue, 3 Mar 2020 23:10:43 -0300 Subject: [PATCH 44/52] [ADD] make_target_name --- sped/relatorios/efd_relatorios.py | 79 +++++++++++++++++-------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 68aa8a3..46ebcaf 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -38,7 +38,7 @@ print('versão atual', "%s.%s.%s" % (python_version[0],python_version[1],python_version[2])) exit() -def make_csv_file(sped_file_path, numero_do_arquivo, lista_de_arquivos): +def make_csv_file(numero_do_arquivo, sped_file_path, lista_de_arquivos): tipo_da_efd = lista_de_arquivos.informations[sped_file_path]['tipo'] codificacao = lista_de_arquivos.informations[sped_file_path]['codificação'] @@ -51,6 +51,31 @@ def make_csv_file(sped_file_path, numero_do_arquivo, lista_de_arquivos): return {numero_do_arquivo: arquivo_csv} +def make_target_name(new_dict): + data_ini = {} + data_fim = {} + + for file_path in new_dict.values(): + # PISCOFINS_20150701_20150731_12345678912345_...csv + # 12345678912345-123456789123-20170101-20170131-1-...-SPED-EFD.csv + data01 = re.search(r'PISCOFINS_(\d{8})_(\d{8})', file_path, flags=re.IGNORECASE) + data02 = re.search(r'\d{14}.\d+.(\d{8}).(\d{8}).*SPED-EFD', file_path, flags=re.IGNORECASE) + + if data01: + data_ini[ data01.group(1) ] = 1 + data_fim[ data01.group(2) ] = 1 + if data02: + data_ini[ data02.group(1) ] = 1 + data_fim[ data02.group(2) ] = 1 + + #print(f'{data_ini = } ; {data_fim = }') + ini = list(sorted(data_ini.keys()))[0] + fim = list(sorted(data_fim.keys()))[-1] + + target = f'Info do Contribuinte - SPED EFD - {ini} a {fim}' + + return target + def main(): print(f'\n Python Sped - versão: {__version__}\n') @@ -120,7 +145,7 @@ def main(): print(f"\nArquivo número {value_1} não encontrado!\n") exit() sped_file = arquivos_sped_efd[value_1 - 1] - arquivos_escolhidos[sped_file] = value_1 + arquivos_escolhidos[value_1] = sped_file elif intervalo_digito: # exemplo: '32..41' value_1 = int(intervalo_digito.group(1)) # 32 @@ -131,18 +156,21 @@ def main(): if value_2 > len(arquivos_sped_efd) or value_2 <= 0: print(f"\nArquivo número {value_2} não encontrado!\n") exit() - if value_1 > value_2: - print(f"\n{value_1}..{value_2}: o primeiro número deve ser menor ou igual ao segundo!\n") - exit() - for index in range(value_1 - 1, value_2): - sped_file = arquivos_sped_efd[index] - arquivos_escolhidos[sped_file] = index + 1 + + if value_2 >= value_1: # ordem crescente + intervalo = range(value_1, value_2 + 1) + else: # ordem decrescente + intervalo = reversed(range(value_2, value_1 + 1)) + + for value in list(intervalo): + sped_file = arquivos_sped_efd[value - 1] + arquivos_escolhidos[value] = sped_file else: print(f"\nOpção {indice} inválida!\n") exit() - print(f"\nArquivo(s) selecionado(s) '{comando_inicial}' -> {list(arquivos_escolhidos.values())}:\n") - for sped_file in arquivos_escolhidos: + print(f"\nArquivo(s) selecionado(s) '{comando_inicial}' -> {list(arquivos_escolhidos.keys())}:\n") + for sped_file in arquivos_escolhidos.values(): print(f'\t{sped_file}') print() @@ -166,43 +194,22 @@ def main(): new_dict = { key: dicts[key] for dicts in output for key in dicts } # dict Comprehensions #print(f'{new_dict = } ; {new_dict.values() = }') - data_ini = {} - data_fim = {} - - for value in new_dict.values(): - # PISCOFINS_20150701_20150731_12345678912345_...csv - # 12345678912345-123456789123-20170101-20170131-1-...-SPED-EFD.csv - data01 = re.search(r'PISCOFINS_(\d{8})_(\d{8})', value, flags=re.IGNORECASE) - data02 = re.search(r'\d{14}.\d+.(\d{8}).(\d{8}).*SPED-EFD', value, flags=re.IGNORECASE) - - if data01: - data_ini[ data01.group(1) ] = 1 - data_fim[ data01.group(2) ] = 1 - if data02: - data_ini[ data02.group(1) ] = 1 - data_fim[ data02.group(2) ] = 1 - - #print(f'{data_ini = } ; {data_fim = }') - - ini = list(sorted(data_ini.keys()))[0] - fim = list(sorted(data_fim.keys()))[-1] - - target = f'Info do Contribuinte - SPED EFD - {ini} a {fim}' + target = make_target_name(new_dict) final_file_csv = target + ".csv" final_file_excel = target + ".xlsx" # unificar todos os arquivos csv no arquivo final_file_csv - with open(final_file_csv, 'w', newline='', encoding='utf-8', errors='ignore') as csvfile: + with open(final_file_csv, 'w', newline='', encoding='utf-8', errors='ignore') as csv_unificado: # imprimir nomes das colunas apenas uma vez na primeira linha nomes_das_colunas = ';'.join(SPED_EFD_Info.colunas_selecionadas) - csvfile.write( nomes_das_colunas + '\n' ) + csv_unificado.write(nomes_das_colunas + '\n') # https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files - for num,csv_file_path in sorted(new_dict.items()): + for num, csv_file_path in new_dict.items(): print(f"arquivo[{num:2d}]: '{csv_file_path}'.") with open(csv_file_path, mode='r', encoding='utf-8', errors='ignore') as f: - csvfile.write(f.read()) # read all lines at once + csv_unificado.write(f.read()) # f.read() all lines at once if os.path.exists(csv_file_path): os.remove(csv_file_path) From 3d6ce6c0032bebf0c464acb848978d5a06810b03 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Wed, 4 Mar 2020 20:15:42 -0300 Subject: [PATCH 45/52] mensagem doc alterada --- sped/relatorios/convert_csv_to_xlsx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sped/relatorios/convert_csv_to_xlsx.py b/sped/relatorios/convert_csv_to_xlsx.py index 0e941d3..e2f9de8 100644 --- a/sped/relatorios/convert_csv_to_xlsx.py +++ b/sped/relatorios/convert_csv_to_xlsx.py @@ -18,7 +18,7 @@ # Python OOP: Atributos e Métodos (def, funções) class CSV_to_Excel: """ - converter arquivo de formato .csv para .xlsx do excel + Converter arquivo de formato CSV para XLSX do Excel """ # initialize the attributes of the class From 1de19349c95968d02cd61e1146ae83ddd0715158 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Wed, 4 Mar 2020 20:17:31 -0300 Subject: [PATCH 46/52] =?UTF-8?q?reorganizada=20as=20mensagens=20de=20exec?= =?UTF-8?q?u=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/efd_relatorios.py | 32 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 46ebcaf..0a84aa6 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '03 de Março de 2020 (início: 29 de Janeiro de 2020)' +Data = '04 de Março de 2020 (início: 29 de Janeiro de 2020)' Home = 'https://github.com/claudiofsr/python-sped' # Instruções (no Linux): @@ -51,7 +51,7 @@ def make_csv_file(numero_do_arquivo, sped_file_path, lista_de_arquivos): return {numero_do_arquivo: arquivo_csv} -def make_target_name(new_dict): +def make_target_name(new_dict,lista_de_arquivos): data_ini = {} data_fim = {} @@ -71,7 +71,7 @@ def make_target_name(new_dict): #print(f'{data_ini = } ; {data_fim = }') ini = list(sorted(data_ini.keys()))[0] fim = list(sorted(data_fim.keys()))[-1] - + target = f'Info do Contribuinte - SPED EFD - {ini} a {fim}' return target @@ -169,11 +169,13 @@ def main(): print(f"\nOpção {indice} inválida!\n") exit() - print(f"\nArquivo(s) selecionado(s) '{comando_inicial}' -> {list(arquivos_escolhidos.keys())}:\n") + print(f"\nArquivo(s) SPED EFD selecionado(s): '{comando_inicial}' -> {list(arquivos_escolhidos.keys())}\n") for sped_file in arquivos_escolhidos.values(): print(f'\t{sped_file}') print() + print(f"Gerar arquivos CSV com as informações do SPED EFD:\n") + start = time() # https://sebastianraschka.com/Articles/2014_multiprocessing.html @@ -181,24 +183,22 @@ def main(): # https://www.programcreek.com/python/index/175/multiprocessing pool = Pool( processes = int(max(1, num_cpus - 2)) ) results = [ pool.apply_async(make_csv_file, args=(k,v,lista_de_arquivos)) for (k,v) in arquivos_escolhidos.items() ] - output = [ p.get() for p in results ] # output = [{num: csv_file_path}] + output = [ p.get() for p in results ] # output = [{num1: csv_file_path1}, {num2: csv_file_path2}, ...] pool.close() - num_total_de_arquivos = len(output) - if num_total_de_arquivos > 1: - print(f"\nForam gerados {num_total_de_arquivos} arquivos csv temporários.\n") - else: - print(f"\nFoi gerado {num_total_de_arquivos} arquivo csv temporário.\n") - # https://stackoverflow.com/questions/5236296/how-to-convert-list-of-dict-to-dict new_dict = { key: dicts[key] for dicts in output for key in dicts } # dict Comprehensions #print(f'{new_dict = } ; {new_dict.values() = }') - target = make_target_name(new_dict) + target = make_target_name(new_dict,lista_de_arquivos) final_file_csv = target + ".csv" final_file_excel = target + ".xlsx" + num_total_de_arquivos = len(new_dict) + if num_total_de_arquivos > 1: + print(f"\nUnificar o(s) {num_total_de_arquivos} arquivo(s) CSV no arquivo '{final_file_csv}'.\n") + # unificar todos os arquivos csv no arquivo final_file_csv with open(final_file_csv, 'w', newline='', encoding='utf-8', errors='ignore') as csv_unificado: # imprimir nomes das colunas apenas uma vez na primeira linha @@ -207,19 +207,21 @@ def main(): # https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files for num, csv_file_path in new_dict.items(): - print(f"arquivo[{num:2d}]: '{csv_file_path}'.") + if num_total_de_arquivos > 1: + print(f"arquivo[{num:2d}]: '{csv_file_path}'.") with open(csv_file_path, mode='r', encoding='utf-8', errors='ignore') as f: csv_unificado.write(f.read()) # f.read() all lines at once if os.path.exists(csv_file_path): os.remove(csv_file_path) + + print(f"\nConverter o arquivo '{final_file_csv}' para o formato XLSX do Excel:\n") + print(f"'{final_file_csv}' -> '{final_file_excel}'.\n") excel_file = CSV_to_Excel(final_file_csv, final_file_excel, verbose=False) excel_file.convert_csv_to_xlsx if os.path.exists(final_file_csv): os.remove(final_file_csv) - - print(f"\nFinalmente, foi gerado o arquivo xlsx do Excel -> '{final_file_excel}'.\n") end = time() From a1c35174bc045e6ac25f3e0fa073cd6b39d47f52 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Wed, 4 Mar 2020 20:23:59 -0300 Subject: [PATCH 47/52] =?UTF-8?q?escolhido=20o=20=20na=20compo?= =?UTF-8?q?si=C3=A7=C3=A3o=20de=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/print_csv_file.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/sped/relatorios/print_csv_file.py b/sped/relatorios/print_csv_file.py index 67847de..79a0ea4 100644 --- a/sped/relatorios/print_csv_file.py +++ b/sped/relatorios/print_csv_file.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '01 de Março de 2020 (início: 10 de Janeiro de 2020)' +Data = '04 de Março de 2020 (início: 10 de Janeiro de 2020)' import os, re, sys, itertools, csv from time import time, sleep @@ -52,8 +52,8 @@ class SPED_EFD_Info: registros_de_chave_eletronica = ['CHV_NFE', 'CHV_CTE', 'CHV_NFSE', 'CHV_DOCe', 'CHV_CFE', 'CHV_NFE_CTE'] # adicionado 'VL_OPR' para EFD ICMS_IPI - registros_de_valor = ['VL_DOC', 'VL_BRT', 'VL_OPER', 'VL_OPR', 'VL_OPER_DEP', 'VL_BC_CRED', 'VL_BC_EST', - 'VL_TOT_REC', 'VL_REC_CAIXA', 'VL_REC_COMP', 'VL_REC', 'VL_ITEM'] + registros_de_valor_do_item = ['VL_DOC', 'VL_BRT', 'VL_OPER', 'VL_OPR', 'VL_OPER_DEP', 'VL_BC_CRED', + 'VL_BC_EST', 'VL_TOT_REC', 'VL_REC_CAIXA', 'VL_REC_COMP', 'VL_REC', 'VL_ITEM'] # Imprimir as informações desta coluna, nesta ordem colunas_selecionadas = [ @@ -69,7 +69,7 @@ class SPED_EFD_Info: # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? registros_totais = set( registros_de_data + registros_de_identificacao_do_item + registros_de_plano_de_contas + - registros_de_codigo_cst + registros_de_chave_eletronica + registros_de_valor + + registros_de_codigo_cst + registros_de_chave_eletronica + registros_de_valor_do_item + colunas_selecionadas) # initialize the attributes of the class @@ -402,11 +402,13 @@ def info_dos_blocos(self,sped_efd,output_filename): my_regex = r'^[A-K]' # Ler os blocos da A a K. + registros_da_bcalc = ['VL_BC_PIS', 'VL_BC_COFINS'] campos_necessarios = ['CST_PIS', 'CST_COFINS', 'VL_BC_PIS', 'VL_BC_COFINS'] # Bastam os seguintes campos, desde que os registros de PIS/PASEP ocorram sempre anteriores aos registros de COFINS: # campos_necessarios = ['CST_COFINS', 'VL_BC_COFINS'] if self.efd_tipo == 'efd_icms_ipi': + registros_da_bcalc = ['VL_BC_ICMS'] campos_necessarios = ['CST_ICMS', 'VL_BC_ICMS'] # https://docs.python.org/3/library/csv.html @@ -444,7 +446,7 @@ def info_dos_blocos(self,sped_efd,output_filename): cst_cofins = '' # 2 caracteres cst_icms = '' # 3 caracteres cfop = 'cfop' # 4 caracteres - valor_item = 'valor_item' + valor_bc = 'valor_bc' for campo in registro.campos: if campo.nome == 'CST_PIS': @@ -455,13 +457,13 @@ def info_dos_blocos(self,sped_efd,output_filename): cst_icms = registro.valores[campo.indice] if campo.nome == 'CFOP': cfop = registro.valores[campo.indice] - if campo.nome in type(self).registros_de_valor: - valor_item = registro.valores[campo.indice] + if campo.nome in registros_da_bcalc: + valor_bc = registro.valores[campo.indice] cst_contribuicao = max(cst_pis,cst_cofins) # Utilizar uma combinação de valores para identificar univocamente um item. - combinacao = f'{cst_contribuicao}_{cst_icms}_{cfop}_{valor_item}' + combinacao = f'{cst_contribuicao}_{cst_icms}_{cfop}_{valor_bc}' if self.verbose: print(f'\ncount = {count:>2} ; key = {key} ; REG = {REG} ; nivel_anterior = {nivel_anterior} ; nivel = {nivel} ; ', end='') @@ -490,7 +492,6 @@ def info_dos_blocos(self,sped_efd,output_filename): # https://www.geeksforgeeks.org/python-creating-multidimensional-dictionary/ info.setdefault(nivel, {}).setdefault(combinacao, {})['Nível Hierárquico'] = nivel - info[nivel][combinacao]['Valor do Item'] = valor_item info[nivel][combinacao]['CST_PIS_COFINS'] = cst_contribuicao for campo in registro.campos: @@ -509,14 +510,14 @@ def info_dos_blocos(self,sped_efd,output_filename): # reter em info{} as informações dos registros contidos em registros_totais info[nivel][combinacao][campo.nome] = valor - - # Informar os campos em registros_de_data_emissao na coluna 'Data de Emissão'. + + # Aparentemenete, o SPED RFB Java escolhe a primeira, quando há duas opções C191/C195, D101/D105, ... + if campo.nome in type(self).registros_de_valor_do_item and 'Valor do Item' not in info[nivel][combinacao]: + info[nivel][combinacao]['Valor do Item'] = valor if campo.nome in type(self).registros_de_data_emissao and len(valor) == 8: info[nivel][combinacao]['Data de Emissão'] = valor - # Informar os campos em registros_de_data_execucao na coluna 'Data de Execução'. if campo.nome in type(self).registros_de_data_execucao and len(valor) == 8: info[nivel][combinacao]['Data de Execução'] = valor - # Informar os campos de chave eletrônica de 44 dígitos na coluna 'Chave Eletrônica'. if campo.nome in type(self).registros_de_chave_eletronica: info[nivel][combinacao]['Chave Eletrônica'] = valor # Informar nomes dos estabelecimentos de cada CNPJ @@ -571,4 +572,4 @@ def info_dos_blocos(self,sped_efd,output_filename): if self.verbose and count > 20: break - print(f"finalizado arquivo {self.numero_do_arquivo:2d} -> '{output_filename}'.") + print(f"arquivo[{self.numero_do_arquivo:2d}]: '{output_filename}'.") From b2e5334243f27b47d4bba01c66b2f55dd11d3436 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Wed, 4 Mar 2020 20:55:47 -0300 Subject: [PATCH 48/52] =?UTF-8?q?adi=C3=A7=C3=A3o=20das=20colunas=20'VL=5F?= =?UTF-8?q?PIS'=20e=20'VL=5FCOFINS'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/print_csv_file.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sped/relatorios/print_csv_file.py b/sped/relatorios/print_csv_file.py index 79a0ea4..8277ba6 100644 --- a/sped/relatorios/print_csv_file.py +++ b/sped/relatorios/print_csv_file.py @@ -62,8 +62,8 @@ class SPED_EFD_Info: 'NAT_BC_CRED', 'CFOP', 'COD_PART', *registros_de_cadastro_do_participante, 'CNPJ_CPF_PART', 'Data de Emissão', 'Data de Execução', 'COD_ITEM', *registros_de_identificacao_do_item, 'Chave Eletrônica', 'COD_MOD', 'NUM_DOC', 'NUM_ITEM', 'COD_CTA', *registros_de_plano_de_contas, - 'Valor do Item', 'VL_BC_PIS', 'VL_BC_COFINS', 'ALIQ_PIS', 'ALIQ_COFINS', - 'VL_ISS', 'CST_ICMS', 'VL_BC_ICMS', 'ALIQ_ICMS' + 'Valor do Item', 'VL_BC_PIS', 'VL_BC_COFINS', 'ALIQ_PIS', 'ALIQ_COFINS', 'VL_PIS', 'VL_COFINS', + 'VL_ISS', 'CST_ICMS', 'VL_BC_ICMS', 'ALIQ_ICMS', 'VL_ICMS' ] # evitar duplicidade: Is there a more Pythonic way to prevent adding a duplicate to a list? From 39587706762ad986fbe5f828997588fe164cbe93 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Wed, 4 Mar 2020 22:49:40 -0300 Subject: [PATCH 49/52] =?UTF-8?q?EFD=20ICMS=5FIPI=20entradas=20e=20sa?= =?UTF-8?q?=C3=ADdas=20de=20acordo=20com=20CFOP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/print_csv_file.py | 32 ++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/sped/relatorios/print_csv_file.py b/sped/relatorios/print_csv_file.py index 8277ba6..eb26a3d 100644 --- a/sped/relatorios/print_csv_file.py +++ b/sped/relatorios/print_csv_file.py @@ -338,14 +338,37 @@ def adicionar_informacoes(self,dict_info): dict_info['Arquivo da SPED EFD'] = self.basename dict_info['Linhas'] = next(type(self).contador_de_linhas) - # re.search: find something anywhere in the string and return a match object. - if 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS']): + if self.efd_tipo == 'efd_contribuicoes': + if 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS']): + cst = int(dict_info['CST_PIS_COFINS']) + if 1 <= cst <= 49: + dict_info['Tipo de Operação'] = 'Saída' + elif 50 <= cst <= 99: + dict_info['Tipo de Operação'] = 'Entrada' + elif self.efd_tipo == 'efd_icms_ipi': + if 'CFOP' in dict_info and re.search(r'\d{4}', dict_info['CFOP']): + cfop = int(dict_info['CFOP']) + if cfop >= 4000: + dict_info['Tipo de Operação'] = 'Saída' + else: + dict_info['Tipo de Operação'] = 'Entrada' + + if (self.efd_tipo == 'efd_contribuicoes' and 'CST_PIS_COFINS' in dict_info + and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS'])): cst = int(dict_info['CST_PIS_COFINS']) if 1 <= cst <= 49: dict_info['Tipo de Operação'] = 'Saída' elif 50 <= cst <= 99: dict_info['Tipo de Operação'] = 'Entrada' + if (self.efd_tipo == 'efd_icms_ipi' and 'CFOP' in dict_info + and re.search(r'\d{4}', dict_info['CFOP'])): + cfop = int(dict_info['CFOP']) + if cfop >= 4000: + dict_info['Tipo de Operação'] = 'Saída' + else: + dict_info['Tipo de Operação'] = 'Entrada' + # adicionar informação de NAT_BC_CRED para os créditos (50 <= cst <= 66) # quando houver informação do CFOP e NAT_BC_CRED estiver vazio. if ('CFOP' in dict_info and 'NAT_BC_CRED' in dict_info @@ -511,10 +534,9 @@ def info_dos_blocos(self,sped_efd,output_filename): # reter em info{} as informações dos registros contidos em registros_totais info[nivel][combinacao][campo.nome] = valor - # Aparentemenete, o SPED RFB Java escolhe a primeira, quando há duas opções C191/C195, D101/D105, ... - if campo.nome in type(self).registros_de_valor_do_item and 'Valor do Item' not in info[nivel][combinacao]: + if campo.nome in type(self).registros_de_valor_do_item: info[nivel][combinacao]['Valor do Item'] = valor - if campo.nome in type(self).registros_de_data_emissao and len(valor) == 8: + if campo.nome in type(self).registros_de_data_emissao and len(valor) == 8: info[nivel][combinacao]['Data de Emissão'] = valor if campo.nome in type(self).registros_de_data_execucao and len(valor) == 8: info[nivel][combinacao]['Data de Execução'] = valor From 1264e1e18a9f61978aa64f608a091b93c2f0a705 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Thu, 5 Mar 2020 10:56:29 -0300 Subject: [PATCH 50/52] =?UTF-8?q?adi=C3=A7=C3=A3o=20de=20requisitos:=20cch?= =?UTF-8?q?ardet=20e=20xlsxwriter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 1ac3664..b1f4868 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,6 @@ Biblioteca para geração dos arquivos do Sistema Público de Escrituração Dig * python * six - * coveralls - * pytest * cchardet * xlsxwriter From e4776a92d3a4a918919b12608c1caeb2aac76c89 Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Thu, 5 Mar 2020 10:59:22 -0300 Subject: [PATCH 51/52] importar csv para escrever e ler os arquivos CSV --- sped/relatorios/efd_relatorios.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sped/relatorios/efd_relatorios.py b/sped/relatorios/efd_relatorios.py index 0a84aa6..6d0608e 100755 --- a/sped/relatorios/efd_relatorios.py +++ b/sped/relatorios/efd_relatorios.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '04 de Março de 2020 (início: 29 de Janeiro de 2020)' +Data = '05 de Março de 2020 (início: 29 de Janeiro de 2020)' Home = 'https://github.com/claudiofsr/python-sped' # Instruções (no Linux): @@ -19,7 +19,7 @@ # execute no terminal o camando: # > efd_relatorios -import sys, os, re +import sys, os, re, csv from time import time, sleep from sped import __version__ from sped.relatorios.find_efd_files import ReadFiles, Total_Execution_Time @@ -200,17 +200,23 @@ def main(): print(f"\nUnificar o(s) {num_total_de_arquivos} arquivo(s) CSV no arquivo '{final_file_csv}'.\n") # unificar todos os arquivos csv no arquivo final_file_csv - with open(final_file_csv, 'w', newline='', encoding='utf-8', errors='ignore') as csv_unificado: - # imprimir nomes das colunas apenas uma vez na primeira linha - nomes_das_colunas = ';'.join(SPED_EFD_Info.colunas_selecionadas) - csv_unificado.write(nomes_das_colunas + '\n') + with open(final_file_csv, mode='w', newline='', encoding='utf-8', errors='ignore') as csv_unificado: + + writer = csv.writer(csv_unificado, delimiter=';') + + # imprimir os nomes das colunas apenas uma vez na primeira linha + writer.writerow(SPED_EFD_Info.colunas_selecionadas) # https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files for num, csv_file_path in new_dict.items(): + if num_total_de_arquivos > 1: print(f"arquivo[{num:2d}]: '{csv_file_path}'.") - with open(csv_file_path, mode='r', encoding='utf-8', errors='ignore') as f: - csv_unificado.write(f.read()) # f.read() all lines at once + + with open(csv_file_path, mode='r', newline='', encoding='utf-8', errors='ignore') as f: + reader = csv.reader(f, delimiter=';') + writer.writerows(reader) # write all lines at once + if os.path.exists(csv_file_path): os.remove(csv_file_path) From bb2578857d3605d427edf649d47d841b4401c38e Mon Sep 17 00:00:00 2001 From: claudiofsr Date: Thu, 5 Mar 2020 11:02:52 -0300 Subject: [PATCH 52/52] =?UTF-8?q?especifica=C3=A7=C3=B5es=20de=20acordo=20?= =?UTF-8?q?com=20o=20tipo=20de=20SPED=20EFD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/relatorios/print_csv_file.py | 43 ++++++++++++------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/sped/relatorios/print_csv_file.py b/sped/relatorios/print_csv_file.py index eb26a3d..219307e 100644 --- a/sped/relatorios/print_csv_file.py +++ b/sped/relatorios/print_csv_file.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- Autor = 'Claudio Fernandes de Souza Rodrigues (claudiofsr@yahoo.com)' -Data = '04 de Março de 2020 (início: 10 de Janeiro de 2020)' +Data = '05 de Março de 2020 (início: 10 de Janeiro de 2020)' import os, re, sys, itertools, csv from time import time, sleep @@ -335,9 +335,11 @@ def adicionar_informacoes(self,dict_info): Adicionar informações em dict_info Formatar alguns de seus campos com o uso de tabelas ou funções """ + dict_info['Arquivo da SPED EFD'] = self.basename dict_info['Linhas'] = next(type(self).contador_de_linhas) + # adicionar informação de 'Tipo de Operação' if self.efd_tipo == 'efd_contribuicoes': if 'CST_PIS_COFINS' in dict_info and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS']): cst = int(dict_info['CST_PIS_COFINS']) @@ -352,22 +354,6 @@ def adicionar_informacoes(self,dict_info): dict_info['Tipo de Operação'] = 'Saída' else: dict_info['Tipo de Operação'] = 'Entrada' - - if (self.efd_tipo == 'efd_contribuicoes' and 'CST_PIS_COFINS' in dict_info - and re.search(r'\d{1,2}', dict_info['CST_PIS_COFINS'])): - cst = int(dict_info['CST_PIS_COFINS']) - if 1 <= cst <= 49: - dict_info['Tipo de Operação'] = 'Saída' - elif 50 <= cst <= 99: - dict_info['Tipo de Operação'] = 'Entrada' - - if (self.efd_tipo == 'efd_icms_ipi' and 'CFOP' in dict_info - and re.search(r'\d{4}', dict_info['CFOP'])): - cfop = int(dict_info['CFOP']) - if cfop >= 4000: - dict_info['Tipo de Operação'] = 'Saída' - else: - dict_info['Tipo de Operação'] = 'Entrada' # adicionar informação de NAT_BC_CRED para os créditos (50 <= cst <= 66) # quando houver informação do CFOP e NAT_BC_CRED estiver vazio. @@ -425,20 +411,22 @@ def info_dos_blocos(self,sped_efd,output_filename): my_regex = r'^[A-K]' # Ler os blocos da A a K. - registros_da_bcalc = ['VL_BC_PIS', 'VL_BC_COFINS'] - campos_necessarios = ['CST_PIS', 'CST_COFINS', 'VL_BC_PIS', 'VL_BC_COFINS'] - # Bastam os seguintes campos, desde que os registros de PIS/PASEP ocorram sempre anteriores aos registros de COFINS: - # campos_necessarios = ['CST_COFINS', 'VL_BC_COFINS'] - - if self.efd_tipo == 'efd_icms_ipi': - registros_da_bcalc = ['VL_BC_ICMS'] + if self.efd_tipo == 'efd_contribuicoes': + registros_de_base_calculo = ['VL_BC_PIS', 'VL_BC_COFINS'] + campos_necessarios = ['CST_PIS', 'CST_COFINS', 'VL_BC_PIS', 'VL_BC_COFINS'] + # Bastariam os seguintes campos, desde que os registros de PIS/PASEP ocorressem sempre anteriores + # aos registros de COFINS: campos_necessarios = ['CST_COFINS', 'VL_BC_COFINS'] + elif self.efd_tipo == 'efd_icms_ipi': + registros_de_base_calculo = ['VL_BC_ICMS'] campos_necessarios = ['CST_ICMS', 'VL_BC_ICMS'] # https://docs.python.org/3/library/csv.html - with open(output_filename, 'w', newline='', encoding='utf-8', errors='ignore') as csvfile: + with open(output_filename, mode='w', newline='', encoding='utf-8', errors='ignore') as csvfile: writer = csv.writer(csvfile, delimiter=';') - #writer.writerow(type(self).colunas_selecionadas) # imprimir nomes das colunas apenas uma vez + + # Os nomes das colunas serão impressos posteriormente em efd_relatorios.py + # writer.writerow(type(self).colunas_selecionadas) for key in sped_efd._blocos.keys(): @@ -480,12 +468,13 @@ def info_dos_blocos(self,sped_efd,output_filename): cst_icms = registro.valores[campo.indice] if campo.nome == 'CFOP': cfop = registro.valores[campo.indice] - if campo.nome in registros_da_bcalc: + if campo.nome in registros_de_base_calculo: valor_bc = registro.valores[campo.indice] cst_contribuicao = max(cst_pis,cst_cofins) # Utilizar uma combinação de valores para identificar univocamente um item. + # O pareamento entre itens de PIS e COFINS ocorre dinamicamente, linha a linha. combinacao = f'{cst_contribuicao}_{cst_icms}_{cfop}_{valor_bc}' if self.verbose: