From 6894193d9d1e457c893475dec4b4d38855def084 Mon Sep 17 00:00:00 2001 From: mstuttgart Date: Mon, 7 Sep 2015 17:34:01 -0300 Subject: [PATCH 01/12] Folder fci com sua estrutura basica adicionada --- sped/fci/__init__.py | 1 + sped/fci/arquivos.py | 1 + sped/fci/blocos.py | 1 + sped/fci/registros.py | 1 + 4 files changed, 4 insertions(+) create mode 100644 sped/fci/__init__.py create mode 100644 sped/fci/arquivos.py create mode 100644 sped/fci/blocos.py create mode 100644 sped/fci/registros.py diff --git a/sped/fci/__init__.py b/sped/fci/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/sped/fci/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/sped/fci/arquivos.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/sped/fci/blocos.py b/sped/fci/blocos.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/sped/fci/blocos.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/sped/fci/registros.py b/sped/fci/registros.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/sped/fci/registros.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- From 0201cf7862d5ef00d701e4134cc7f7800f370ec1 Mon Sep 17 00:00:00 2001 From: lfdivino Date: Thu, 17 Sep 2015 11:47:36 -0300 Subject: [PATCH 02/12] =?UTF-8?q?[NEW]=20Adicionado=20m=C3=B3dulo=20FCI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 + sped/arquivos.py | 4 +- sped/fci/arquivos.py | 76 ++++++++++++++++++ sped/fci/blocos.py | 55 +++++++++++++ sped/fci/registros.py | 179 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 317 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9b4ec02..0188491 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ nosetests.xml # Pycharm .idea +main.py # Vim @@ -42,3 +43,6 @@ dist/ build/ .eggs/ *.egg-info + +main.py + diff --git a/sped/arquivos.py b/sped/arquivos.py index abe4982..6e15649 100644 --- a/sped/arquivos.py +++ b/sped/arquivos.py @@ -6,6 +6,7 @@ class ArquivoDigital(object): + registro_abertura = None registro_fechamento = None registros = None @@ -27,7 +28,7 @@ def read_registro(self, line): try: registro_class = getattr(self.__class__.registros, 'Registro' + reg_id) except AttributeError: - raise RuntimeError("Arquivo inválido para EFD - PIS/COFINS") + raise RuntimeError(u"Arquivo inválido para EFD - PIS/COFINS") registro = registro_class(line) @@ -47,6 +48,7 @@ def write_to(self, buffer): bloco = self._blocos[key] reg_count += len(bloco.registros) for r in bloco.registros: + a = r.as_line() buffer.write(r.as_line() + u'\r\n') self._registro_fechamento[2] = reg_count diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py index 40a96af..f78fcb8 100644 --- a/sped/fci/arquivos.py +++ b/sped/fci/arquivos.py @@ -1 +1,77 @@ # -*- coding: utf-8 -*- + +from ..arquivos import ArquivoDigital +from . import blocos +from . import registros +from .blocos import Bloco0 +from .blocos import Bloco5 +from .blocos import Bloco9 +from .registros import Registro0000 +from .registros import Registro9999 + + +class ArquivoDigital(ArquivoDigital): + + registro_abertura = Registro0000 + registro_fechamento = Registro9999 + registros = registros + blocos = blocos + + def __init__(self): + super(ArquivoDigital, self).__init__() + self._blocos['0'] = Bloco0() + self._blocos['5'] = Bloco5() + self._blocos['9'] = Bloco9() + + def read_registro(self, line): + + # caso o usuario insira linha sem pip + pipe = '|' if line[0] != '|' else '' + line = pipe + line + reg_id = line.split('|')[1] + + try: + registro_class = \ + getattr(self.__class__.registros, 'Registro' + reg_id) + except AttributeError: + raise RuntimeError(u"Arquivo inválido para FCI") + + registro = registro_class(line) + if registro.__class__ == self.__class__.registro_abertura: + self._registro_abertura = registro + elif registro.__class__ == self.__class__.registro_fechamento: + self._registro_fechamento = registro + elif registro.__class__ == \ + self.__class__.blocos.Bloco0.registro_abertura: + self.blocos.Bloco0.abertura = registro + else: + if reg_id == '9900' and (len(self._blocos['9'].registros)) == 4: + registro._valores[3] = str((len(self._blocos['5'].registros))-2) + + bloco_id = reg_id[0] + bloco = self._blocos[bloco_id] + bloco.add(registro) + + def write_to(self, buffer): + + self._adiciona_registro_fixo_bloco9() + + linha_abertura = self._registro_abertura.as_line()[1:] + buffer.write(linha_abertura + u'\r\n') + reg_count = 2 + for key in self._blocos.keys(): + bloco = self._blocos[key] + reg_count += len(bloco.registros) + for r in bloco.registros: + a = r.as_line() + a = a[1:] + buffer.write(a + u'\r\n') + + self._registro_fechamento[2] = reg_count + linha_fechamento = self._registro_fechamento.as_line()[1:] + buffer.write(linha_fechamento + u'\r\n') + + def _adiciona_registro_fixo_bloco9(self): + self.read_registro('|9900|0000|1') + self.read_registro('|9900|0010|1') + self.read_registro('|9900|5020|') diff --git a/sped/fci/blocos.py b/sped/fci/blocos.py index 40a96af..e787fe6 100644 --- a/sped/fci/blocos.py +++ b/sped/fci/blocos.py @@ -1 +1,56 @@ # -*- coding: utf-8 -*- + +from ..blocos import Bloco + +from .registros import Registro0001 +from .registros import Registro0990 +from .registros import Registro5001 +from .registros import Registro5990 +from .registros import Registro9001 +from .registros import Registro9990 + + +class Bloco0(Bloco): + """ + Cabeçalho da FCI: Identificação do contribuinte + """ + registro_abertura = Registro0001 + registro_fechamento = Registro0990 + + @property + def abertura(self): + registro = self.__class__.registro_abertura() + return registro + + @property + def fechamento(self): + registro = self.__class__.registro_fechamento() + # Define a quantidade de registros + registro[2] = len(self._registros) + 3 + return registro + + def add(self, registro): + self._registros.append(registro) + + +class Bloco5(Bloco): + registro_abertura = Registro5001 + registro_fechamento = Registro5990 + + @property + def abertura(self): + registro = self.__class__.registro_abertura() + return registro + + +class Bloco9(Bloco): + """ + Controle e Encerramento do Arquivo Digital + """ + registro_abertura = Registro9001 + registro_fechamento = Registro9990 + + @property + def abertura(self): + registro = self.__class__.registro_abertura() + return registro diff --git a/sped/fci/registros.py b/sped/fci/registros.py index 40a96af..6fc4436 100644 --- a/sped/fci/registros.py +++ b/sped/fci/registros.py @@ -1 +1,180 @@ # -*- coding: utf-8 -*- + +from ..campos import * +from ..registros import Registro +from ..erros import CampoError + + +class Registro0000(Registro): + campos = [ + CampoFixo(1, 'REG', '0000'), + CampoAlfanumerico(2, 'CNPJ_CONTRIBUINTE'), + CampoAlfanumerico(3, 'NOME_CONTRIBUINTE'), + CampoFixo(4, 'VERSAO_LEIAUTE', '1.0') + ] + + +class Registro0001(Registro): + campos = [ + CampoFixo(1, 'REG', "0001"), + CampoAlfanumerico(2, 'TEXTO_PADRAO_UTF8', obrigatorio=True, ) + ] + + +class Registro0010(Registro): + campos = [ + CampoFixo(1, 'REG', '0010'), + CampoAlfanumerico(2, 'CNPJ_CONTRIBUINTE', obrigatorio=True), + CampoAlfanumerico(3, 'NOME_RAZAO_SOCIAL', obrigatorio=True), + CampoAlfanumerico(4, 'INSCRICAO_ESTADUAL', obrigatorio=True), + CampoAlfanumerico(5, 'ENDERECO_ESTABELECIMENTO', obrigatorio=True), + CampoNumerico(6, 'CEP', obrigatorio=True), + CampoAlfanumerico(7, 'MUNICIPIO', obrigatorio=True), + CampoAlfanumerico(8, 'UF', obrigatorio=True) + ] + + +class Registro0990(Registro): + campos = [ + CampoFixo(1, 'REG', '0990'), + CampoNumerico(2, 'QUANTIDADE_LINHAS') + ] + + def __init__(self, line=None): + if not line: + self._valores = [''] * (len(self.campos) + 1) + for c in self.campos: + if isinstance(c, CampoFixo): + self._valores[c.indice] = c.valor + else: + self._valores = line.split('|') + for c in self.campos: + if isinstance(c, CampoFixo): + if self._valores[c.indice] != c.valor: + raise CampoError(self, c.nome) + + +class Registro5001(Registro): + campos = [ + CampoFixo(1, 'REG', '5001'), + ] + + def __init__(self, line=None): + if not line: + self._valores = [''] * (len(self.campos) + 1) + for c in self.campos: + if isinstance(c, CampoFixo): + self._valores[c.indice] = c.valor + else: + self._valores = line.split('|') + for c in self.campos: + if isinstance(c, CampoFixo): + if self._valores[c.indice] != c.valor: + raise CampoError(self, c.nome) + + +class Registro5020(Registro): + campos = [ + CampoFixo(1, 'REG', '5020'), + CampoAlfanumerico(2, 'NOME_MERCADORIA', obrigatorio=True, tamanho=255), + CampoNumerico(3, 'CODIGO_NCM', obrigatorio=True), + CampoAlfanumerico(4, 'CODIGO_MERCADORIA', tamanho=50, + obrigatorio=True), + CampoNumerico(5, 'CODIGO_GTIN'), + CampoAlfanumerico(6, 'UNIDADE_MERCADORIA', tamanho=6, + obrigatorio=True), + CampoNumerico(7, 'VALOR_SAIDA_MERCADORIA_INTERESTADUAL', precisao=2, + obrigatorio=True), + CampoNumerico(8, 'VALOR_PARCELA_IMPORTADA_EXTERIOR', precisao=2, + obrigatorio=True), + CampoNumerico(9, 'CONTEUDO_IMPORTACAO_CI', precisao=2, + minimo=Decimal(0), maximo=Decimal(100), + obrigatorio=True), + ] + + +class Registro5990(Registro): + campos = [ + CampoFixo(1, 'REG', '5990'), + CampoNumerico(2, 'QUANTIDADE_LINHAS'), + ] + + def __init__(self, line=None): + if not line: + self._valores = [''] * (len(self.campos) + 1) + for c in self.campos: + if isinstance(c, CampoFixo): + self._valores[c.indice] = c.valor + else: + self._valores = line.split('|') + for c in self.campos: + if isinstance(c, CampoFixo): + if self._valores[c.indice] != c.valor: + raise CampoError(self, c.nome) + + +class Registro9001(Registro): + campos = [ + CampoFixo(1, 'REG', '9001') + ] + + def __init__(self, line=None): + if not line: + self._valores = [''] * (len(self.campos) + 1) + for c in self.campos: + if isinstance(c, CampoFixo): + self._valores[c.indice] = c.valor + else: + self._valores = line.split('|') + for c in self.campos: + if isinstance(c, CampoFixo): + if self._valores[c.indice] != c.valor: + raise CampoError(self, c.nome) + + +class Registro9900(Registro): + campos = [ + CampoFixo(1, 'REG', '9900'), + CampoAlfanumerico(2, 'REG_SER_TOTALIZADO', tamanho=4), + CampoNumerico(3, 'QUANTIDADE_LINHAS_REGISTRO_ANTERIOR') + ] + + +class Registro9990(Registro): + campos = [ + CampoFixo(1, 'REG', '9990'), + CampoNumerico(2, 'QUANTIDADE_LINHAS') + ] + + def __init__(self, line=None): + if not line: + self._valores = [''] * (len(self.campos) + 1) + for c in self.campos: + if isinstance(c, CampoFixo): + self._valores[c.indice] = c.valor + else: + self._valores = line.split('|') + for c in self.campos: + if isinstance(c, CampoFixo): + if self._valores[c.indice] != c.valor: + raise CampoError(self, c.nome) + + +class Registro9999(Registro): + campos = [ + CampoFixo(1, 'REG', '9999'), + CampoNumerico(2, ' QUANTIDADE_LINHAS_ARQUIVO') + ] + + def __init__(self, line=None): + if not line: + self._valores = [''] * (len(self.campos) + 1) + for c in self.campos: + if isinstance(c, CampoFixo): + self._valores[c.indice] = c.valor + else: + self._valores = line.split('|') + for c in self.campos: + if isinstance(c, CampoFixo): + if self._valores[c.indice] != c.valor: + raise CampoError(self, c.nome) From 6260d30ece6aff9f06c082dcd41e8e57ca45ce6c Mon Sep 17 00:00:00 2001 From: mstuttgart Date: Fri, 18 Sep 2015 17:38:29 -0300 Subject: [PATCH 03/12] [NEW] Adiciona testes e ajustes no calculo da numero de produtos da FCI --- .gitignore | 2 -- .travis.yml | 1 + README.md | 8 +++++ sped/fci/arquivos.py | 20 ++++++------- sped/fci/blocos.py | 1 + test/__init__.py | 1 + test/fci_test.py | 69 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 test/__init__.py create mode 100644 test/fci_test.py diff --git a/.gitignore b/.gitignore index 0188491..11fc32a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,6 @@ nosetests.xml # Pycharm .idea -main.py # Vim @@ -44,5 +43,4 @@ build/ .eggs/ *.egg-info -main.py diff --git a/.travis.yml b/.travis.yml index 98af1bc..bd00833 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ install: - pip install coveralls script: - coverage run --source=sped setup.py test + - python test/fci_teste.py deploy: provider: pypi user: ginx diff --git a/README.md b/README.md index 708f698..887ceae 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ O projeto está em fase inicial de desenvolvimento e **não deve** ser usado em | ECF | Funcional | | EFD-PIS/COFINS | Funcional | | EFD-ICMS/IPI | Funcional | +| FCI | Funcional | ### ECD @@ -75,3 +76,10 @@ Este módulo está funcional, com todos seus registros codificados, porém muito adequada, consultado tabelas externas por exemplo, ou validando corretamente todos os tamanhos de campos. Ele pode ser usado para gerar um arquivo digital, com validações de abertura e fechamento de bloco automaticamente. + +### FCI + +Este módulo está funcional, com todos seus registros codificados, porém muitos campos ainda não possuem uma validação +adequada, validando corretamente todos os tamanhos de campos. + +Ele pode ser usado para gerar um arquivo digital, com validações de abertura e fechamento de bloco automaticamente. diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py index f78fcb8..640ad15 100644 --- a/sped/fci/arquivos.py +++ b/sped/fci/arquivos.py @@ -23,6 +23,10 @@ def __init__(self): self._blocos['5'] = Bloco5() self._blocos['9'] = Bloco9() + self.read_registro('|9900|0000|1') + self.read_registro('|9900|0010|1') + self.read_registro('|9900|5020|') + def read_registro(self, line): # caso o usuario insira linha sem pip @@ -45,16 +49,17 @@ def read_registro(self, line): self.__class__.blocos.Bloco0.registro_abertura: self.blocos.Bloco0.abertura = registro else: - if reg_id == '9900' and (len(self._blocos['9'].registros)) == 4: - registro._valores[3] = str((len(self._blocos['5'].registros))-2) - bloco_id = reg_id[0] bloco = self._blocos[bloco_id] bloco.add(registro) - def write_to(self, buffer): + # Contabiliza os registros 5020 + if reg_id == '5020': + registros_9 = self._blocos['9'].registros[3] + registros_9.valores[3] = \ + str((len(self._blocos['5'].registros))-2) - self._adiciona_registro_fixo_bloco9() + def write_to(self, buffer): linha_abertura = self._registro_abertura.as_line()[1:] buffer.write(linha_abertura + u'\r\n') @@ -70,8 +75,3 @@ def write_to(self, buffer): self._registro_fechamento[2] = reg_count linha_fechamento = self._registro_fechamento.as_line()[1:] buffer.write(linha_fechamento + u'\r\n') - - def _adiciona_registro_fixo_bloco9(self): - self.read_registro('|9900|0000|1') - self.read_registro('|9900|0010|1') - self.read_registro('|9900|5020|') diff --git a/sped/fci/blocos.py b/sped/fci/blocos.py index e787fe6..5d81f0f 100644 --- a/sped/fci/blocos.py +++ b/sped/fci/blocos.py @@ -54,3 +54,4 @@ class Bloco9(Bloco): def abertura(self): registro = self.__class__.registro_abertura() return registro + diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/test/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/test/fci_test.py b/test/fci_test.py new file mode 100644 index 0000000..b24c90f --- /dev/null +++ b/test/fci_test.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +import unittest +import os +import sys + +# Necessário para que o arquivo de testes encontre +test_root = os.path.dirname(os.path.abspath(__file__)) +os.chdir(test_root) +sys.path.insert(0, os.path.dirname(test_root)) +sys.path.insert(0, test_root) + +from sped.fci import arquivos + + +class TestArquivoDigital(unittest.TestCase): + + def test_read_registro(self): + txt = u"""0000|11111111000191|EMPRESA TESTE|1.0 +0001|Texto em caracteres UTF-8: (dígrafo BR)\"ção\",(dígrafo espanholenhe)\"ñ\",(trema)\"Ü\",(ordinais)\"ªº\",(ligamento s+z alemão)\"ß\" +0010|46377222000129|Contribuinte de Teste S/A|686001664111|Rua XV de novembro, 1.234|01506000|São João|SP +0990|4 +5001 +5020|Motor de pistão por ignição, cilindrada igual a 2.000 cm³ - R123-A4-5|84073490|12j8ai.5d0-ao4p|07123456789012|unid|9123,45|4567,89|50,07 +5020|Motor de pistão por ignição, cilindrada igual a 2.000 cm³ - R123-A4-5|84073490|12j8ai.5d0-ao4p|07123456789012|unid|9123,45|4567,89|50,07 +5020|Motor de pistão por ignição, cilindrada igual a 2.000 cm³ - R123-A4-5|84073490|12j8ai.5d0-ao4p|07123456789012|unid|9123,45|4567,89|50,07 +5990|5 +9001 +9900|0000|1 +9900|0010|1 +9900|5020|3 +9990|5 +9999|15 +""".replace('\n', '\r\n') + + # Permite validacao de string grandes + self.maxDiff = None + arq = arquivos.ArquivoDigital() + + arq.read_registro('0000|11111111000191|EMPRESA TESTE|1.0') + + arq.read_registro(u'0001|Texto em caracteres UTF-8: ' + u'(dígrafo BR)\"ção\",(dígrafo espanholenhe)\"ñ\",' + u'(trema)\"Ü\",(ordinais)\"ªº\",(ligamento s+z ' + u'alemão)\"ß\"') + + arq.read_registro( u'|0010|46377222000129|Contribuinte de Teste ' + u'S/A|686001664111|Rua XV de novembro, 1.234|' + u'01506000|São João|SP') + + arq.read_registro(u'|5020|Motor de pistão por ignição, cilindrada ' + u'igual a 2.000 cm³ - R123-A4-5|84073490|' + u'12j8ai.5d0-ao4p|07123456789012|unid|9123,45|' + u'4567,89|50,07') + + arq.read_registro(u'|5020|Motor de pistão por ignição, cilindrada ' + u'igual a 2.000 cm³ - R123-A4-5|84073490|' + u'12j8ai.5d0-ao4p|07123456789012|unid|9123,45|' + u'4567,89|50,07') + + arq.read_registro(u'|5020|Motor de pistão por ignição, cilindrada ' + u'igual a 2.000 cm³ - R123-A4-5|84073490|' + u'12j8ai.5d0-ao4p|07123456789012|unid|9123,45|' + u'4567,89|50,07') + + self.assertEqual(txt, arq.getstring()) + +if __name__ == '__main__': + unittest.main() From 8f28263d762fbec76ed96f297e495c7b04db86bf Mon Sep 17 00:00:00 2001 From: Bianca Date: Mon, 21 Sep 2015 15:04:43 -0300 Subject: [PATCH 04/12] =?UTF-8?q?Corre=C3=A7=C3=B5es=20importa=C3=A7=C3=A3?= =?UTF-8?q?o/exporta=C3=A7=C3=A3o=20arquivo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/arquivos.py | 2 +- sped/fci/arquivos.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sped/arquivos.py b/sped/arquivos.py index 6e15649..ea9d9ec 100644 --- a/sped/arquivos.py +++ b/sped/arquivos.py @@ -20,7 +20,7 @@ def __init__(self): def readfile(self, filename): with open(filename) as file: for line in [line.rstrip('\r\n') for line in file]: - self.read_registro(line) + self.read_registro(line.decode('utf8')) def read_registro(self, line): reg_id = line.split('|')[1] diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py index 640ad15..20a5b82 100644 --- a/sped/fci/arquivos.py +++ b/sped/fci/arquivos.py @@ -11,7 +11,6 @@ class ArquivoDigital(ArquivoDigital): - registro_abertura = Registro0000 registro_fechamento = Registro9999 registros = registros @@ -57,7 +56,7 @@ def read_registro(self, line): if reg_id == '5020': registros_9 = self._blocos['9'].registros[3] registros_9.valores[3] = \ - str((len(self._blocos['5'].registros))-2) + str((len(self._blocos['5'].registros)) - 2) def write_to(self, buffer): @@ -75,3 +74,11 @@ def write_to(self, buffer): self._registro_fechamento[2] = reg_count linha_fechamento = self._registro_fechamento.as_line()[1:] buffer.write(linha_fechamento + u'\r\n') + + + def readfile(self, filename): + + with open(filename) as file: + for line in [line.rstrip('\r\n') for line in file]: + if line[:4]!='9900': + self.read_registro(line.decode('utf8')) From 3ab598d7eaea754a851ab3ca8fb0e90b299d647f Mon Sep 17 00:00:00 2001 From: Bianca Date: Mon, 21 Sep 2015 16:23:59 -0300 Subject: [PATCH 05/12] Adicionados campos de retorno FCI --- sped/fci/registros.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sped/fci/registros.py b/sped/fci/registros.py index 6fc4436..81d4404 100644 --- a/sped/fci/registros.py +++ b/sped/fci/registros.py @@ -10,14 +10,19 @@ class Registro0000(Registro): CampoFixo(1, 'REG', '0000'), CampoAlfanumerico(2, 'CNPJ_CONTRIBUINTE'), CampoAlfanumerico(3, 'NOME_CONTRIBUINTE'), - CampoFixo(4, 'VERSAO_LEIAUTE', '1.0') + CampoFixo(4, 'VERSAO_LEIAUTE', '1.0'), + CampoAlfanumerico(5, 'HASH CODE',obrigatorio=False, tamanho=47), + CampoAlfanumerico(6, 'DT_RECEPCAO_ARQUIVO',obrigatorio=False, tamanho=20), + CampoAlfanumerico(7, 'COD_RECEPCAO_ARQUIVO',obrigatorio=False, tamanho=36), + CampoAlfanumerico(8, 'DT_VALIDACAO_ARQUIVO', obrigatorio=False, tamanho=20), + CampoAlfanumerico(9, 'IN_VALIDACAO_ARQUIVO',obrigatorio=False, tamanho=20) ] class Registro0001(Registro): campos = [ CampoFixo(1, 'REG', "0001"), - CampoAlfanumerico(2, 'TEXTO_PADRAO_UTF8', obrigatorio=True, ) + CampoAlfanumerico(2, 'TEXTO_PADRAO_UTF8', obrigatorio=True ) ] @@ -78,11 +83,9 @@ class Registro5020(Registro): CampoFixo(1, 'REG', '5020'), CampoAlfanumerico(2, 'NOME_MERCADORIA', obrigatorio=True, tamanho=255), CampoNumerico(3, 'CODIGO_NCM', obrigatorio=True), - CampoAlfanumerico(4, 'CODIGO_MERCADORIA', tamanho=50, - obrigatorio=True), + CampoAlfanumerico(4, 'CODIGO_MERCADORIA', obrigatorio=True, tamanho=50), CampoNumerico(5, 'CODIGO_GTIN'), - CampoAlfanumerico(6, 'UNIDADE_MERCADORIA', tamanho=6, - obrigatorio=True), + CampoAlfanumerico(6, 'UNIDADE_MERCADORIA', tamanho=6, obrigatorio=True), CampoNumerico(7, 'VALOR_SAIDA_MERCADORIA_INTERESTADUAL', precisao=2, obrigatorio=True), CampoNumerico(8, 'VALOR_PARCELA_IMPORTADA_EXTERIOR', precisao=2, @@ -90,6 +93,9 @@ class Registro5020(Registro): CampoNumerico(9, 'CONTEUDO_IMPORTACAO_CI', precisao=2, minimo=Decimal(0), maximo=Decimal(100), obrigatorio=True), + CampoAlfanumerico(10, 'CODIGO_FCI', obrigatorio=False, tamanho=36), + CampoAlfanumerico(11, 'IN_VALIDACAO_FICHA', obrigatorio=False, tamanho=20) + ] @@ -163,7 +169,7 @@ def __init__(self, line=None): class Registro9999(Registro): campos = [ CampoFixo(1, 'REG', '9999'), - CampoNumerico(2, ' QUANTIDADE_LINHAS_ARQUIVO') + CampoNumerico(2, 'QUANTIDADE_LINHAS_ARQUIVO') ] def __init__(self, line=None): From 0e63f9a71c57d7fd70990f608d99b91447957ef3 Mon Sep 17 00:00:00 2001 From: biancatella Date: Fri, 25 Sep 2015 10:27:59 -0300 Subject: [PATCH 06/12] Ajustes: strings(encode) e contadores de blocos --- sped/fci/arquivos.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py index 20a5b82..54469b2 100644 --- a/sped/fci/arquivos.py +++ b/sped/fci/arquivos.py @@ -22,6 +22,8 @@ def __init__(self): self._blocos['5'] = Bloco5() self._blocos['9'] = Bloco9() + self.read_registro( + u"""0001|Texto em caracteres UTF-8: (dígrafo BR)\"ção\",(dígrafo espanholenhe)\"ñ\",(trema)\"Ü\",(ordinais)\"ªº\",(ligamento s+z alemão)\"ß\"""") self.read_registro('|9900|0000|1') self.read_registro('|9900|0010|1') self.read_registro('|9900|5020|') @@ -75,10 +77,9 @@ def write_to(self, buffer): linha_fechamento = self._registro_fechamento.as_line()[1:] buffer.write(linha_fechamento + u'\r\n') - def readfile(self, filename): with open(filename) as file: for line in [line.rstrip('\r\n') for line in file]: - if line[:4]!='9900': - self.read_registro(line.decode('utf8')) + if (line[:4] != '9900' and line[:4] != '0001' and line[:4] != '0990'): + self.read_registro(line.decode('utf-8-sig')) From e66ca2256253c2e4b3e28834c9e2bd361e0f8d11 Mon Sep 17 00:00:00 2001 From: biancatella Date: Tue, 3 Nov 2015 14:37:07 -0200 Subject: [PATCH 07/12] =?UTF-8?q?Corre=C3=A7=C3=B5es=20gera=C3=A7=C3=A3o?= =?UTF-8?q?=20arquivo=20fci?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/arquivos.py | 7 +++++++ sped/fci/arquivos.py | 11 +++++++---- sped/registros.py | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/sped/arquivos.py b/sped/arquivos.py index ea9d9ec..51d5049 100644 --- a/sped/arquivos.py +++ b/sped/arquivos.py @@ -59,3 +59,10 @@ def getstring(self): buffer = StringIO() self.write_to(buffer) return buffer.getvalue() + + # def getFile(self): + # from tempfile import TemporaryFile + # tmp = TemporaryFile() + # self.write_to(tmp) + # tmp.seek(0) + # return tmp \ No newline at end of file diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py index 54469b2..e275ec2 100644 --- a/sped/fci/arquivos.py +++ b/sped/fci/arquivos.py @@ -22,8 +22,10 @@ def __init__(self): self._blocos['5'] = Bloco5() self._blocos['9'] = Bloco9() - self.read_registro( - u"""0001|Texto em caracteres UTF-8: (dígrafo BR)\"ção\",(dígrafo espanholenhe)\"ñ\",(trema)\"Ü\",(ordinais)\"ªº\",(ligamento s+z alemão)\"ß\"""") + utf = (u"0001|Texto em caracteres UTF-8: (dígrafo BR)'ção',(dígrafo esp" + u"anhol-enhe)'ñ',(trema)'Ü',(ordinais)'ªº',(ligamento s+z ale" + u"mão)'ß'.") + self.read_registro(utf) self.read_registro('|9900|0000|1') self.read_registro('|9900|0010|1') self.read_registro('|9900|5020|') @@ -77,9 +79,10 @@ def write_to(self, buffer): linha_fechamento = self._registro_fechamento.as_line()[1:] buffer.write(linha_fechamento + u'\r\n') + def readfile(self, filename): - with open(filename) as file: + with open(filename) as file: for line in [line.rstrip('\r\n') for line in file]: - if (line[:4] != '9900' and line[:4] != '0001' and line[:4] != '0990'): + if (line[:4]!='9900' and line[:4]!='0001' and line[:4]!='0990'): self.read_registro(line.decode('utf-8-sig')) diff --git a/sped/registros.py b/sped/registros.py index 08b7745..e29553d 100644 --- a/sped/registros.py +++ b/sped/registros.py @@ -113,4 +113,5 @@ def __setattr__(self, name, value): campo.set(self, value) def as_line(self): + aux = self._valores return '|'.join(self._valores) From f0d82c807aa0a4d2cbf267edf64886cc0d29aae1 Mon Sep 17 00:00:00 2001 From: biancatella Date: Tue, 3 Nov 2015 15:10:17 -0200 Subject: [PATCH 08/12] =?UTF-8?q?Corre=C3=A7=C3=B5es=20flake=208?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/fci/arquivos.py | 11 +++++------ sped/fci/blocos.py | 1 - sped/fci/registros.py | 26 ++++++++++++++++---------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py index e275ec2..08bd8d3 100644 --- a/sped/fci/arquivos.py +++ b/sped/fci/arquivos.py @@ -22,9 +22,9 @@ def __init__(self): self._blocos['5'] = Bloco5() self._blocos['9'] = Bloco9() - utf = (u"0001|Texto em caracteres UTF-8: (dígrafo BR)'ção',(dígrafo esp" - u"anhol-enhe)'ñ',(trema)'Ü',(ordinais)'ªº',(ligamento s+z ale" - u"mão)'ß'.") + utf = (u"0001|Texto em caracteres UTF-8: (dígrafo BR)'ção',(dígrafo " + u"espanhol-enhe)'ñ',(trema)'Ü',(ordinais)'ªº',(ligamento s+z a" + u"lemão)'ß'.") self.read_registro(utf) self.read_registro('|9900|0000|1') self.read_registro('|9900|0010|1') @@ -79,10 +79,9 @@ def write_to(self, buffer): linha_fechamento = self._registro_fechamento.as_line()[1:] buffer.write(linha_fechamento + u'\r\n') - def readfile(self, filename): - with open(filename) as file: + with open(filename) as file: for line in [line.rstrip('\r\n') for line in file]: - if (line[:4]!='9900' and line[:4]!='0001' and line[:4]!='0990'): + if (line[:4] != '9900' and line[:4] != '0001' and line[:4] != '0990'): self.read_registro(line.decode('utf-8-sig')) diff --git a/sped/fci/blocos.py b/sped/fci/blocos.py index 5d81f0f..e787fe6 100644 --- a/sped/fci/blocos.py +++ b/sped/fci/blocos.py @@ -54,4 +54,3 @@ class Bloco9(Bloco): def abertura(self): registro = self.__class__.registro_abertura() return registro - diff --git a/sped/fci/registros.py b/sped/fci/registros.py index 81d4404..bf23b2e 100644 --- a/sped/fci/registros.py +++ b/sped/fci/registros.py @@ -11,18 +11,22 @@ class Registro0000(Registro): CampoAlfanumerico(2, 'CNPJ_CONTRIBUINTE'), CampoAlfanumerico(3, 'NOME_CONTRIBUINTE'), CampoFixo(4, 'VERSAO_LEIAUTE', '1.0'), - CampoAlfanumerico(5, 'HASH CODE',obrigatorio=False, tamanho=47), - CampoAlfanumerico(6, 'DT_RECEPCAO_ARQUIVO',obrigatorio=False, tamanho=20), - CampoAlfanumerico(7, 'COD_RECEPCAO_ARQUIVO',obrigatorio=False, tamanho=36), - CampoAlfanumerico(8, 'DT_VALIDACAO_ARQUIVO', obrigatorio=False, tamanho=20), - CampoAlfanumerico(9, 'IN_VALIDACAO_ARQUIVO',obrigatorio=False, tamanho=20) + CampoAlfanumerico(5, 'HASH CODE', obrigatorio=False, tamanho=47), + CampoAlfanumerico(6, 'DT_RECEPCAO_ARQUIVO', obrigatorio=False, + tamanho=20), + CampoAlfanumerico(7, 'COD_RECEPCAO_ARQUIVO', obrigatorio=False, + tamanho=36), + CampoAlfanumerico(8, 'DT_VALIDACAO_ARQUIVO', obrigatorio=False, + tamanho=20), + CampoAlfanumerico(9, 'IN_VALIDACAO_ARQUIVO', obrigatorio=False, + tamanho=20) ] class Registro0001(Registro): campos = [ CampoFixo(1, 'REG', "0001"), - CampoAlfanumerico(2, 'TEXTO_PADRAO_UTF8', obrigatorio=True ) + CampoAlfanumerico(2, 'TEXTO_PADRAO_UTF8', obrigatorio=True) ] @@ -83,9 +87,11 @@ class Registro5020(Registro): CampoFixo(1, 'REG', '5020'), CampoAlfanumerico(2, 'NOME_MERCADORIA', obrigatorio=True, tamanho=255), CampoNumerico(3, 'CODIGO_NCM', obrigatorio=True), - CampoAlfanumerico(4, 'CODIGO_MERCADORIA', obrigatorio=True, tamanho=50), + CampoAlfanumerico(4, 'CODIGO_MERCADORIA', obrigatorio=True, + tamanho=50), CampoNumerico(5, 'CODIGO_GTIN'), - CampoAlfanumerico(6, 'UNIDADE_MERCADORIA', tamanho=6, obrigatorio=True), + CampoAlfanumerico(6, 'UNIDADE_MERCADORIA', tamanho=6, + obrigatorio=True), CampoNumerico(7, 'VALOR_SAIDA_MERCADORIA_INTERESTADUAL', precisao=2, obrigatorio=True), CampoNumerico(8, 'VALOR_PARCELA_IMPORTADA_EXTERIOR', precisao=2, @@ -94,8 +100,8 @@ class Registro5020(Registro): minimo=Decimal(0), maximo=Decimal(100), obrigatorio=True), CampoAlfanumerico(10, 'CODIGO_FCI', obrigatorio=False, tamanho=36), - CampoAlfanumerico(11, 'IN_VALIDACAO_FICHA', obrigatorio=False, tamanho=20) - + CampoAlfanumerico(11, 'IN_VALIDACAO_FICHA', obrigatorio=False, + tamanho=20) ] From 798286f3b826aa6b58fbbaf462278611c221715b Mon Sep 17 00:00:00 2001 From: Bianca Tella Date: Wed, 4 Nov 2015 10:28:41 -0200 Subject: [PATCH 09/12] Update .travis.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correção no nome do arquivo de teste. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bd00833..85761d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ install: - pip install coveralls script: - coverage run --source=sped setup.py test - - python test/fci_teste.py + - python test/fci_test.py deploy: provider: pypi user: ginx From 3bd7b5d212a28db73b939838c0a866f98f143960 Mon Sep 17 00:00:00 2001 From: biancatella Date: Wed, 4 Nov 2015 16:46:29 -0200 Subject: [PATCH 10/12] =?UTF-8?q?altera=C3=A7=C3=B5es=20sugeridas=20pelo?= =?UTF-8?q?=20landscape?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/arquivos.py | 8 -------- sped/fci/arquivos.py | 18 +++++++++--------- sped/fci/blocos.py | 12 ++++++------ sped/fci/registros.py | 3 +-- sped/registros.py | 1 - test/fci_test.py | 9 ++++----- 6 files changed, 20 insertions(+), 31 deletions(-) diff --git a/sped/arquivos.py b/sped/arquivos.py index 51d5049..37f062a 100644 --- a/sped/arquivos.py +++ b/sped/arquivos.py @@ -48,7 +48,6 @@ def write_to(self, buffer): bloco = self._blocos[key] reg_count += len(bloco.registros) for r in bloco.registros: - a = r.as_line() buffer.write(r.as_line() + u'\r\n') self._registro_fechamento[2] = reg_count @@ -59,10 +58,3 @@ def getstring(self): buffer = StringIO() self.write_to(buffer) return buffer.getvalue() - - # def getFile(self): - # from tempfile import TemporaryFile - # tmp = TemporaryFile() - # self.write_to(tmp) - # tmp.seek(0) - # return tmp \ No newline at end of file diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py index 08bd8d3..0f9281e 100644 --- a/sped/fci/arquivos.py +++ b/sped/fci/arquivos.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- from ..arquivos import ArquivoDigital -from . import blocos -from . import registros -from .blocos import Bloco0 -from .blocos import Bloco5 -from .blocos import Bloco9 -from .registros import Registro0000 -from .registros import Registro9999 +import blocos +import registros +from blocos import Bloco0 +from blocos import Bloco5 +from blocos import Bloco9 +from registros import Registro0000 +from registros import Registro9999 class ArquivoDigital(ArquivoDigital): @@ -81,7 +81,7 @@ def write_to(self, buffer): def readfile(self, filename): - with open(filename) as file: - for line in [line.rstrip('\r\n') for line in file]: + with open(filename) as arq: + for line in [line.rstrip('\r\n') for line in arq]: if (line[:4] != '9900' and line[:4] != '0001' and line[:4] != '0990'): self.read_registro(line.decode('utf-8-sig')) diff --git a/sped/fci/blocos.py b/sped/fci/blocos.py index e787fe6..62b354e 100644 --- a/sped/fci/blocos.py +++ b/sped/fci/blocos.py @@ -2,12 +2,12 @@ from ..blocos import Bloco -from .registros import Registro0001 -from .registros import Registro0990 -from .registros import Registro5001 -from .registros import Registro5990 -from .registros import Registro9001 -from .registros import Registro9990 +from registros import Registro0001 +from registros import Registro0990 +from registros import Registro5001 +from registros import Registro5990 +from registros import Registro9001 +from registros import Registro9990 class Bloco0(Bloco): diff --git a/sped/fci/registros.py b/sped/fci/registros.py index bf23b2e..5df534c 100644 --- a/sped/fci/registros.py +++ b/sped/fci/registros.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from ..campos import * +from ..campos import CampoFixo, CampoAlfanumerico, CampoNumerico from ..registros import Registro from ..erros import CampoError @@ -97,7 +97,6 @@ class Registro5020(Registro): CampoNumerico(8, 'VALOR_PARCELA_IMPORTADA_EXTERIOR', precisao=2, obrigatorio=True), CampoNumerico(9, 'CONTEUDO_IMPORTACAO_CI', precisao=2, - minimo=Decimal(0), maximo=Decimal(100), obrigatorio=True), CampoAlfanumerico(10, 'CODIGO_FCI', obrigatorio=False, tamanho=36), CampoAlfanumerico(11, 'IN_VALIDACAO_FICHA', obrigatorio=False, diff --git a/sped/registros.py b/sped/registros.py index e29553d..08b7745 100644 --- a/sped/registros.py +++ b/sped/registros.py @@ -113,5 +113,4 @@ def __setattr__(self, name, value): campo.set(self, value) def as_line(self): - aux = self._valores return '|'.join(self._valores) diff --git a/test/fci_test.py b/test/fci_test.py index b24c90f..3b23ae5 100644 --- a/test/fci_test.py +++ b/test/fci_test.py @@ -17,7 +17,7 @@ class TestArquivoDigital(unittest.TestCase): def test_read_registro(self): txt = u"""0000|11111111000191|EMPRESA TESTE|1.0 -0001|Texto em caracteres UTF-8: (dígrafo BR)\"ção\",(dígrafo espanholenhe)\"ñ\",(trema)\"Ü\",(ordinais)\"ªº\",(ligamento s+z alemão)\"ß\" +0001|Texto em caracteres UTF-8: (dígrafo BR)'ção',(dígrafo espanhol-enhe)'ñ',(trema)'Ü',(ordinais)'ªº',(ligamento s+z alemão)'ß'. 0010|46377222000129|Contribuinte de Teste S/A|686001664111|Rua XV de novembro, 1.234|01506000|São João|SP 0990|4 5001 @@ -39,10 +39,9 @@ def test_read_registro(self): arq.read_registro('0000|11111111000191|EMPRESA TESTE|1.0') - arq.read_registro(u'0001|Texto em caracteres UTF-8: ' - u'(dígrafo BR)\"ção\",(dígrafo espanholenhe)\"ñ\",' - u'(trema)\"Ü\",(ordinais)\"ªº\",(ligamento s+z ' - u'alemão)\"ß\"') + arq.read_registro(u"|0001|Texto em caracteres UTF-8: (dígrafo BR)'ção'," + u"(dígrafo espanhol-enhe)'ñ',(trema)'Ü',(ordinais" + u")'ªº',(ligamento s+z alemão)'ß'.") arq.read_registro( u'|0010|46377222000129|Contribuinte de Teste ' u'S/A|686001664111|Rua XV de novembro, 1.234|' From a9040e4daa6596aa8df65d53750794264d6b9cb0 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Wed, 4 Nov 2015 22:36:42 -0200 Subject: [PATCH 11/12] Adicionado unittest para rodar junto to setup: python setup.py test --- setup.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/setup.py b/setup.py index a178d7a..686703e 100644 --- a/setup.py +++ b/setup.py @@ -18,9 +18,19 @@ def finalize_options(self): self.test_suite = True def run_tests(self): + # doctest import sys import pytest + errno = pytest.main(self.pytest_args) + + # unittest + import unittest + from test.fci_test import TestArquivoDigital + + suite = unittest.TestLoader().loadTestsFromTestCase(TestArquivoDigital) + unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(errno) From 72142691c131013f03ee0e14064cd985ef125605 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Wed, 4 Nov 2015 22:45:46 -0200 Subject: [PATCH 12/12] =?UTF-8?q?Corre=C3=A7=C3=B5es=20para=20Python=203.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sped/fci/arquivos.py | 14 +++++++------- sped/fci/blocos.py | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sped/fci/arquivos.py b/sped/fci/arquivos.py index 0f9281e..72439b8 100644 --- a/sped/fci/arquivos.py +++ b/sped/fci/arquivos.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- from ..arquivos import ArquivoDigital -import blocos -import registros -from blocos import Bloco0 -from blocos import Bloco5 -from blocos import Bloco9 -from registros import Registro0000 -from registros import Registro9999 +from . import registros +from . import blocos +from .blocos import Bloco0 +from .blocos import Bloco5 +from .blocos import Bloco9 +from .registros import Registro0000 +from .registros import Registro9999 class ArquivoDigital(ArquivoDigital): diff --git a/sped/fci/blocos.py b/sped/fci/blocos.py index 62b354e..e787fe6 100644 --- a/sped/fci/blocos.py +++ b/sped/fci/blocos.py @@ -2,12 +2,12 @@ from ..blocos import Bloco -from registros import Registro0001 -from registros import Registro0990 -from registros import Registro5001 -from registros import Registro5990 -from registros import Registro9001 -from registros import Registro9990 +from .registros import Registro0001 +from .registros import Registro0990 +from .registros import Registro5001 +from .registros import Registro5990 +from .registros import Registro9001 +from .registros import Registro9990 class Bloco0(Bloco):