Skip to content
This repository was archived by the owner on Nov 2, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ dist/
build/
.eggs/
*.egg-info


1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ install:
- pip install coveralls
script:
- coverage run --source=sped setup.py test
- python test/fci_test.py
deploy:
provider: pypi
user: ginx
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
10 changes: 10 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
5 changes: 3 additions & 2 deletions sped/arquivos.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


class ArquivoDigital(object):

registro_abertura = None
registro_fechamento = None
registros = None
Expand All @@ -19,15 +20,15 @@ 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]

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)

Expand Down
1 change: 1 addition & 0 deletions sped/fci/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-
87 changes: 87 additions & 0 deletions sped/fci/arquivos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-

from ..arquivos import ArquivoDigital
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):
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()

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')
self.read_registro('|9900|5020|')

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:
bloco_id = reg_id[0]
bloco = self._blocos[bloco_id]
bloco.add(registro)

# 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)

def write_to(self, buffer):

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 readfile(self, filename):

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'))
56 changes: 56 additions & 0 deletions sped/fci/blocos.py
Original file line number Diff line number Diff line change
@@ -0,0 +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
Loading