sped-br / python-sped

Biblioteca para geração dos arquivos do Sistema Público de Escrituração Digital (SPED) para Python.
MIT License
47 stars 56 forks source link

Exemplo #1

Closed eduardokum closed 9 years ago

eduardokum commented 9 years ago

Olá amigo, estou vendo seu projeto, estou pensando em utiliza-lo, integrando com meu ERP em php, você tem algum arquivo de exemplo de utilização?

Obrigado

sergiogarciadev commented 9 years ago

Segue exemplo com base no código do meu ERP para geração do ECD do ano de 2014.

Infelizmente meu ERP não está pronto e nem possuirá código aberto (a principio).

Este código possui diversas coisas hard code para maquiar parametros que ainda não existem no meu ERP.

Com o código abaixo, o ECD foi entregue gerado pelo sistema (tendo que ser validado e assinado no PVA) sem nenhum erro ou aviso.

O python-sped não exime o programador de conhecer a legislação do SPED e seguir sua documentação, ele apenas faz com que os arquivos sejam gerados sem erros de inconsistências. Validações mais elaboradas ficam a cargo do programador e/ou contador no PVA.

def sped_ecd(request):
    start_date = date(2014, 1, 1)
    end_date = date(2014, 12, 31)

    periods = Period.objects.filter(start_date__gte=start_date, end_date__lte=end_date).order_by('start_date')
    accounts = Account.objects.all().order_by('code')

    first_period = periods.first()
    last_period = periods.last()

    PeriodicBalance.calculate_for(last_period, True)

    #
    # Abertura do Arquivo
    #
    arquivo = ArquivoDigital()
    registro_abertura = arquivo._registro_abertura
    registro_abertura.DT_INI = start_date
    registro_abertura.DT_FIN = end_date
    registro_abertura.NOME = 'SUA EMPRESA LTDA'
    registro_abertura.CNPJ = '00000000000000'
    registro_abertura.UF = 'PR'
    registro_abertura.COD_MUN = 4106902
    registro_abertura.IM = '00000'
    registro_abertura.IND_SIT_INI_PER = '3'
    registro_abertura.IND_NIRE = '1'
    registro_abertura.IND_FIN_ESC = '0'
    registro_abertura.IND_GRANDE_PORTE = '0'
    registro_abertura.TIP_ECD = '0'

    bloco_0 = arquivo._blocos['0']

    registro_0007 = Registro0007()
    registro_0007.COD_ENT_REF = '00'
    bloco_0.add(registro_0007)

    bloco_i = arquivo._blocos['I']

    registro_i010 = RegistroI010()
    registro_i010.IND_ESC = 'G'            # Livro Diário Completo
    registro_i010.COD_VER_LC = '3.00'
    bloco_i.add(registro_i010)

    registro_i030 = RegistroI030()
    registro_i030.DNRC_ABERT = 'TERMO DE ABERTURA'
    registro_i030.NUM_ORD = 5
    registro_i030.NAT_LIVR = 'DIÁRIO GERAL'
    registro_i030.NOME = arquivo._registro_abertura.NOME
    registro_i030.NIRE = '000000'
    registro_i030.CNPJ = arquivo._registro_abertura.CNPJ
    registro_i030.DT_ARQ = date(2014, 1, 10)
    registro_i030.DESC_MUN = 'CURITIBA'
    registro_i030.DT_EX_SOCIAL = end_date
    bloco_i.add(registro_i030)

    for account in accounts:
        if not account.data['reference_account']:
            continue

        registro_i050 = RegistroI050()
        registro_i050.DT_ALT = start_date
        # TODO: Cadastrar a natureza na conta
        account_nature = '%02d' % (4 if int(account.get_root().code[0]) == 3 else int(account.get_root().code[0]))
        registro_i050.COD_NAT = account_nature
        registro_i050.IND_CTA = account.type
        registro_i050.NIVEL = account.level + 1
        registro_i050.COD_CTA = account.code
        if account.parent is not None:
            registro_i050.COD_CTA_SUP = account.parent.code
        registro_i050.CTA = account.name
        bloco_i.add(registro_i050)

        if account.type == Account.ANALYTICAL:
            registro_i051 = RegistroI051()
            registro_i051.COD_ENT_REF = '2'  # PJ Lucro Presumido
            registro_i051.COD_CTA_REF = account.data['reference_account']
            bloco_i.add(registro_i051)

            registro_i052 = RegistroI052()
            registro_i052.COD_AGL = account.code
            bloco_i.add(registro_i052)

    for period in periods:
        registro_i150 = RegistroI150()
        registro_i150.DT_INI = period.start_date
        registro_i150.DT_FIN = period.end_date
        bloco_i.add(registro_i150)

        for account in accounts.filter(type=Account.ANALYTICAL):
            periodic_balance = PeriodicBalance.objects.filter(period=period, account=account).first()

            if not periodic_balance:
                continue

            if not periodic_balance.initial_balance and \
               not periodic_balance.debit_value and \
               not periodic_balance.credit_value and \
               not periodic_balance.final_balance:
                continue

            registro_i155 = RegistroI155()
            registro_i155.COD_CTA = account.code
            registro_i155.VL_SLD_INI = abs(periodic_balance.initial_balance)
            registro_i155.IND_DC_INI = 'C' if periodic_balance.initial_balance > 0 else 'D'
            registro_i155.VL_DEB = abs(periodic_balance.debit_value)
            registro_i155.VL_CRED = abs(periodic_balance.credit_value)
            registro_i155.VL_SLD_FIN = abs(periodic_balance.final_balance)
            registro_i155.IND_DC_FIN = 'C' if periodic_balance.final_balance > 0 else 'D'
            bloco_i.add(registro_i155)

    for entry in Entry.objects.filter(date__gte=start_date,
                                      date__lte=end_date):
        registro_i200 = RegistroI200()
        registro_i200.NUM_LCTO = str(entry.id)
        registro_i200.DT_LCTO = entry.date
        registro_i200.VL_LCTO = entry.value

        if entry.memo == 'APURAÇÃO RESULTADO 12/2014':
            registro_i200.IND_LCTO = 'E'  # N or E
        else:
            registro_i200.IND_LCTO = 'N'  # N or E

        bloco_i.add(registro_i200)

        for item in entry.items.all():
            registro_i250 = RegistroI250()
            registro_i250.COD_CTA = item.account.code
            registro_i250.VL_DC = abs(item.credit_value or item.debit_value)
            registro_i250.IND_DC = 'C' if item.credit_value else 'D'
            registro_i250.HIST = entry.memo
            bloco_i.add(registro_i250)

    registro = RegistroI350()
    registro.DT_RES = end_date
    bloco_i.add(registro)

    PeriodicBalance.calculate_for(last_period, False)

    for account in accounts.filter(code__startswith='3', type=Account.ANALYTICAL):
        periodic_balance = PeriodicBalance.objects.filter(period=last_period, account=account).first()

        if not periodic_balance:
            continue

        registro_i355 = RegistroI355()
        registro_i355.COD_CTA = account.code
        registro_i355.VL_CTA = abs(periodic_balance.final_balance)
        registro_i355.IND_DC = account.nature
        bloco_i.add(registro_i355)

    bloco_j = arquivo._blocos['J']
    registro_j005 = RegistroJ005()
    registro_j005.DT_INI = start_date
    registro_j005.DT_FIN = end_date
    registro_j005.ID_DEM = 1
    bloco_j.add(registro_j005)

    #
    # Calculo Balanco Patrimonial
    #

    PeriodicBalance.calculate_for(last_period, True)

    for account in accounts.filter(Q(code__startswith='1') | Q(code__startswith='2')):
        first_balance = PeriodicBalance.objects.filter(period=first_period, account=account).first()
        last_balance = PeriodicBalance.objects.filter(period=last_period, account=account).first()

        if not first_balance.initial_balance and not last_balance.final_balance:
            continue

        registro_j100 = RegistroJ100()

        registro_j100.COD_AGL = account.code
        registro_j100.NIVEL_AGL = account.level + 1
        registro_j100.DESCR_COD_AGL = account.name
        registro_j100.IND_GRP_BAL = account.code[:1]

        registro_j100.VL_CTA_INI = abs(first_balance.initial_balance)
        registro_j100.IND_DC_BAL_INI = 'C' if first_balance.initial_balance >= 0 else 'D'
        registro_j100.VL_CTA = abs(last_balance.final_balance)
        registro_j100.IND_DC_BAL = 'C' if last_balance.final_balance >= 0 else 'D'

        bloco_j.add(registro_j100)

    #
    # Calculo Resultado (DRE)
    #
    res = dict([(account, Decimal(0)) for account in accounts.filter(code__startswith='3')])

    for item in EntryItem.all_objects.filter(entry__memo='APURAÇÃO RESULTADO 12/2014', account__code__startswith='3'):
        account = item.account
        while account:
            res[account] += (item.credit_value - item.debit_value)
            account = account.parent

    for account in accounts.filter(Q(level=2) | Q(level=4), code__startswith='3').order_by('code'):
        registro_j150 = RegistroJ150()
        if account.nature == Account.ANALYTICAL:
            registro_j150.COD_AGL = account.code
        registro_j150.NIVEL_AGL = account.level + 1
        registro_j150.DESCR_COD_AGL = account.name

        if not res[account]:
            continue

        registro_j150.VL_CTA = abs(res[account])

        if res[account] >= Decimal(0):
            registro_j150.IND_VL = 'D' if account.nature == Account.ANALYTICAL else 'N'
        else:
            registro_j150.IND_VL = 'R' if account.nature == Account.ANALYTICAL else 'P'

        bloco_j.add(registro_j150)

    #
    # Encerramento
    #
    registro_j900 = RegistroJ900()
    registro_j900.DNRC_ENCER = 'TERMO DE ENCERRAMENTO'
    registro_j900.NUM_ORD = 5
    registro_j900.NAT_LIVRO = 'DIÁRIO GERAL'
    registro_j900.NOME = 'SUA EMPRESA LTDA'
    registro_j900.DT_INI_ESCR = start_date
    registro_j900.DT_FIN_ESCR = end_date
    bloco_j.add(registro_j900)

    # Dados do Socio
    registro_j930 = RegistroJ930()
    registro_j930.IDENT_NOM = 'ADMINSTRADOR DA SILVA'
    registro_j930.IDENT_CPF = '0000000000000'
    registro_j930.IDENT_QUALIF = 'Administrador'
    registro_j930.COD_ASSIN = '205'
    registro_j930.EMAIL = 'voce@suaempresa.com.br'
    registro_j930.FONE = '00000'
    bloco_j.add(registro_j930)

    # Dados do Contador
    registro_j930 = RegistroJ930()
    registro_j930.IDENT_NOM = 'CONTADOR DA SILVA'
    registro_j930.IDENT_CPF = '0000000000000'
    registro_j930.IDENT_QUALIF = 'Contador'
    registro_j930.COD_ASSIN = '900'
    registro_j930.EMAIL = 'contador@suaempresa.com.br'
    registro_j930.FONE = '00000'

    registro_j930.IND_CRC = '00000/O'
    registro_j930.UF_CRC = 'PR'
    registro_j930.NUM_SEQ_CRC = 'PR/2015/000000'
    registro_j930.DT_CRC = date(2015, 6, 30)
    bloco_j.add(registro_j930)

    response = HttpResponse(content_type='text/plain; charset=iso-8859-1')
    response['Content-Disposition'] = 'attachment; filename="sped.txt"'

    arquivo.prepare()
    registro_i030.QTD_LIN = arquivo._registro_fechamento[2]
    registro_j900.QTD_LIN = arquivo._registro_fechamento[2]
    arquivo.write_to(response)

    return response