Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI #2

Merged
merged 4 commits into from
Oct 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Empty file added PyNFSe/cli/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions PyNFSe/cli/cadastro/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .ambiente import ambiente, retornar_ambiente
from .configuracao import configuracao, retornar_configuracao
from .lote_rps import lote_rps
from .prestador import prestador, retornar_prestador
from .servico import servico
from .tomador import tomador, retornar_tomador
27 changes: 27 additions & 0 deletions PyNFSe/cli/cadastro/ambiente.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import json

import click

from PyNFSe.cli import constants
from PyNFSe.utils.entidades import Ambiente


def ambiente(ambiente):
click.echo('### Configuração ambiente {}'.format(ambiente))
amb = Ambiente()

amb.numero_rps = click.prompt('Número inicial do rps', type=int, default=1)
amb.numero_lote = click.prompt('Número inicial do lote rps', type=int, default=1)
amb.certificado = click.prompt('Caminho para o certificado', type=str)
amb.senha = click.prompt('Senha certificado', type=str)

return amb


def retornar_ambiente(producao):
if producao:
ambiente = constants.JSON_AMBIENTE_PRODUCAO
else:
ambiente = constants.JSON_AMBIENTE_HOMOLOGACAO
with open(ambiente) as file:
return Ambiente(**json.load(file))
55 changes: 55 additions & 0 deletions PyNFSe/cli/cadastro/configuracao.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import json

import click

from PyNFSe.utils.entidades import Configuracao
from PyNFSe.cli import constants


def configuracao():
conf = Configuracao()

conf.simples = int(click.prompt('Simples Nacional (1 - Sim / 2 - Não)', type=click.Choice(['1', '2'])))
conf.incentivo = int(
click.prompt('Incentivador Cultural (1 - Sim / 2 - Não)', type=click.Choice(['1', '2'])))

conf.iss_retido = int(click.prompt('ISS Retido padrão (1 - Sim / 2 - Não)', type=click.Choice(['1', '2'])))
conf.regime_especial = int(click.prompt('Regime Especial (0 para ver as opções)',
type=click.Choice(['0', '1', '2', '3', '4'])))
while conf.regime_especial == 0:
click.echo(
'1 - ME Municipal\n'
'2 - Estimativa\n'
'3 - Sociedade de profissionais\n'
'4 - Cooperativa\n'
)
conf.regime_especial = int(click.prompt('Regime Especial (0 para ver as opções)',
type=click.Choice(['0', '1', '2', '3', '4'])))

conf.natureza_operacao = int(click.prompt('Natureza da Operação (0 para ver as opções)',
type=click.Choice(['0', '1', '2', '3', '4', '5', '6'])))
while conf.natureza_operacao == 0:
click.echo(
'1 - Tributação no município\n'
'2 - Tributação fora do município\n'
'3 - Isenção\n'
'4 - Imune\n'
'5 –Exigibilidade suspensa por decisão judicial\n'
'6 - Exigibilidade suspensa por procedimento administrativo\n'
)
conf.natureza_operacao = int(click.prompt('Natureza da Operação (0 para ver as opções)',
type=click.Choice(['0', '1', '2', '3', '4', '5', '6'])))

conf.codigo_municipio = click.prompt('Código do município padrão', type=str)
conf.item_lista = click.prompt('Código de item da lista de serviço padrão', type=str)
conf.codigo_tributacao_municipio = click.prompt('Código de Tributação padrão', type=str,
default=conf.item_lista)
conf.codigo_cnae = click.prompt('Código CNAE padrão', type=int)
conf.aliquota = click.prompt('Aliquota padrão')

return conf


def retornar_configuracao():
with open(constants.JSON_CONFIGURACAO) as file:
return Configuracao(**json.load(file))
29 changes: 29 additions & 0 deletions PyNFSe/cli/cadastro/lote_rps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from datetime import datetime

from PyNFSe.utils.entidades import LoteRPS, RPS


def lote_rps(prestador, tomador, servico, ambiente, configuracao):
rps = RPS()
lote = LoteRPS()

rps.identificador = 'N{}'.format(ambiente.numero_rps)
rps.data_emissao = datetime.today()
rps.servico = servico.__dict__
rps.prestador = prestador.__dict__
rps.tomador = tomador.__dict__
rps.simples = configuracao.simples
rps.incentivo = configuracao.incentivo
rps.numero = ambiente.numero_rps
rps.serie = 'A1'
rps.tipo = '1'
rps.natureza_operacao = configuracao.natureza_operacao
rps.regime_especial = configuracao.regime_especial

lote.identificador = 'L{}'.format(ambiente.numero_lote)
lote.numero_lote = ambiente.numero_lote
lote.cnpj = prestador.cnpj
lote.inscricao_municipal = prestador.inscricao_municipal
lote.lista_rps = [rps.__dict__]

return lote
20 changes: 20 additions & 0 deletions PyNFSe/cli/cadastro/prestador.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import json

import click

from PyNFSe.utils.entidades import Prestador
from PyNFSe.cli import constants


def prestador():
click.echo('### Cadastro do Prestador ###')
prestador = Prestador()
prestador.cnpj = click.prompt('Informe o CNPJ', type=str)
prestador.inscricao_municipal = click.prompt('Informe a Inscrição Municipal', type=str)

return prestador


def retornar_prestador():
with open(constants.JSON_PRESTADOR) as file:
return Prestador(**json.load(file))
20 changes: 20 additions & 0 deletions PyNFSe/cli/cadastro/servico.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from decimal import Decimal

import click

from PyNFSe.cli import constants
from PyNFSe.utils.entidades import Servico


def servico():
servico = Servico()
servico.valor_servico = Decimal(click.prompt('Valor serviço'))
servico.iss_retido = int(click.prompt('ISS Retido (1 - Sim / 2 - Não)', type=click.Choice(['1', '2']), default=constants.ISS_RETIDO))
servico.item_lista = click.prompt('Código de item da lista de serviço', default=constants.ITEM_LISTA)
servico.discriminacao = click.prompt('Discriminação do serviço prestado')
servico.codigo_municipio = click.prompt('Código do município', default=constants.CODIGO_MUNICIPIO)
servico.codigo_cnae = click.prompt('Código CNAE', type=int, default=constants.CODIGO_CNAE)
servico.codigo_tributacao_municipio = click.prompt('Código de Tributação', default=servico.item_lista)
servico.aliquota = Decimal(click.prompt('Aliquota', default=constants.ALIQUOTA))

return servico
50 changes: 50 additions & 0 deletions PyNFSe/cli/cadastro/tomador.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import json

import click

from PyNFSe.cli import constants
from PyNFSe.utils.entidades import Tomador


def tomador():
tomador = Tomador()
tomador.tipo_documento = click.prompt('Tipo Documento', type=click.Choice(['cpf', 'cnpj']), default='cnpj').upper()
tomador.numero_documento = click.prompt('Número Documento')
tomador.razao_social = click.prompt('Razão Social')

if tomador.tipo_documento == 'CNPJ':
tomador.inscricao_municipal = click.prompt('Inscrição Municipal (0 para em branco)')
if tomador.inscricao_municipal == '0':
tomador.inscricao_municipal = None

tomador.endereco = click.prompt('Endereço (Apenas a rua)')
tomador.endereco_numero = click.prompt('Número endereço')

tomador.endereco_complemento = click.prompt('Complemento endereço (0 para em branco)')
if tomador.endereco_complemento == '0':
tomador.endereco_complemento = None

tomador.bairro = click.prompt('Bairro')
tomador.codigo_municipio = click.prompt('Código Município', default=constants.CODIGO_MUNICIPIO)
tomador.uf = click.prompt('UF')
tomador.cep = click.prompt('CEP')

tomador.telefone = click.prompt('Telefone (0 para em branco)')
if tomador.telefone == '0':
tomador.telefone = None

tomador.email = click.prompt('Email (0 para em branco)')
if tomador.email == '0':
tomador.email = None

return tomador


def retornar_tomador():
numero_doc = click.prompt('Numero documento')
with open(constants.JSON_TOMADORES, mode='r') as file:
clientes = json.load(file)
try:
return Tomador(**clientes[numero_doc])
except KeyError:
click.echo('{} não cadastrado'.format(numero_doc))
96 changes: 96 additions & 0 deletions PyNFSe/cli/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import click
import json
import os


from PyNFSe.cli import constants
from PyNFSe.cli import helpers
from PyNFSe.cli import cadastro


@click.group()
def cli():
pass


@cli.command()
def configurar_cli():
helpers.criar_diretorio(constants.DIR_PYNFSE)

if helpers.criar_arquivo_json(constants.JSON_PRESTADOR):
prestador = cadastro.prestador()
helpers.salvar_arquivo_json(constants.JSON_PRESTADOR, prestador)

if helpers.criar_arquivo_json(constants.JSON_CONFIGURACAO):
configuracao = cadastro.configuracao()
helpers.salvar_arquivo_json(constants.JSON_CONFIGURACAO, configuracao)

if helpers.criar_arquivo_json(constants.JSON_AMBIENTE_PRODUCAO):
ambiente = cadastro.ambiente('Produção')
helpers.salvar_arquivo_json(constants.JSON_AMBIENTE_PRODUCAO, ambiente)

ambiente_teste = click.prompt('Deseja cadastar ambiente homologação (s/n)', type=click.Choice(['s', 'n']),
default='s')
if ambiente_teste == 's':
if helpers.criar_arquivo_json(constants.JSON_AMBIENTE_HOMOLOGACAO):
ambiente = cadastro.ambiente('Homologação')
helpers.salvar_arquivo_json(constants.JSON_AMBIENTE_HOMOLOGACAO, ambiente)

helpers.criar_arquivo_json(constants.JSON_TOMADORES)


@cli.command()
def cadastrar_tomador():
if not os.path.exists(constants.DIR_PYNFSE):
print('pynfse não configurado. Execute "python pynfse.py configurar_cli" e siga os passos.')
return

tomador = cadastro.tomador()

with open(constants.JSON_TOMADORES, mode='r') as file:
json_file = json.load(file)

with open(constants.JSON_TOMADORES, mode='w') as file:
json_file[tomador.numero_documento] = tomador.__dict__
json.dump(json_file, file, ensure_ascii=False)


@cli.command()
@click.option('--producao', is_flag=True)
def emitir_nfse(producao):

ambiente = cadastro.retornar_ambiente(producao)
configuracao = cadastro.retornar_configuracao()
prestador = cadastro.retornar_prestador()
tomador = cadastro.retornar_tomador()
while not tomador:
tomador = cadastro.retornar_tomador()

servico = cadastro.servico()

servico.__init__()

lote = cadastro.lote_rps(prestador, tomador, servico, ambiente, configuracao)

retorno = helpers.enviar_lote(lote.__dict__, ambiente, producao)


ambiente.numero_lote += 1
ambiente.numero_rps += 1

if producao:
helpers.salvar_arquivo_json(constants.JSON_AMBIENTE_PRODUCAO, ambiente)
else:
helpers.salvar_arquivo_json(constants.JSON_AMBIENTE_HOMOLOGACAO, ambiente)

print(retorno)


@cli.command()
def listar_cliente():
with open(constants.JSON_TOMADORES, mode='r') as file:
tomadores = json.load(file)

for num_doc in tomadores:
tomador = tomadores[num_doc]
print('{0} - {1}'.format(tomador['razao_social'], tomador['numero_documento']))
25 changes: 25 additions & 0 deletions PyNFSe/cli/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import json
import os


def _retorna_parametro(parametro):
try:
with open(JSON_CONFIGURACAO, mode='r') as file:
return json.load(file)[parametro]
except FileNotFoundError:
return None



HOME_FOLDER = os.path.expanduser('~')
DIR_PYNFSE = os.path.join(HOME_FOLDER, '.pynfse')
JSON_PRESTADOR = os.path.join(DIR_PYNFSE, 'prestador.json')
JSON_CONFIGURACAO = os.path.join(DIR_PYNFSE, 'configuracao.json')
JSON_AMBIENTE_PRODUCAO = os.path.join(DIR_PYNFSE, 'ambiente_producao.json')
JSON_AMBIENTE_HOMOLOGACAO = os.path.join(DIR_PYNFSE, 'ambiente_homologacao.json')
JSON_TOMADORES = os.path.join(DIR_PYNFSE, 'clientes.json')
ISS_RETIDO = _retorna_parametro('iss_retido')
CODIGO_MUNICIPIO = _retorna_parametro('codigo_municipio')
ITEM_LISTA = _retorna_parametro('item_lista')
CODIGO_CNAE = _retorna_parametro('codigo_cnae')
ALIQUOTA = _retorna_parametro('aliquota')
41 changes: 41 additions & 0 deletions PyNFSe/cli/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import json
import os

from PyNFSe.nfse.pr.curitiba import NFSeCuritiba


def home_folder():
return os.path.expanduser('~')


def criar_diretorio(directory):
path = os.path.join(home_folder(), directory)

try:
os.mkdir(path)
print('Diretório {} criado'.format(directory))
except FileExistsError:
print('O diretório {} já existe'.format(directory))


def criar_arquivo_json(filename):
if not os.path.exists(filename):
with open(filename, mode='w') as file:
json.dump({}, file)
print('Arquivo {} criado'.format(filename))
return True
else:
print('O arquivo {} já existe'.format(filename))
return False


def salvar_arquivo_json(arquivo_json, obj):
with open(arquivo_json, mode='w') as file:
json.dump(obj.__dict__, file, ensure_ascii=False)


def enviar_lote(lote_rps, ambiente, producao):
ambiente = ambiente
cliente = NFSeCuritiba(ambiente.certificado, ambiente.senha, producao=producao)

return cliente.recepcionar_lote_rps(lote_rps)
1 change: 1 addition & 0 deletions PyNFSe/utils/entidades/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
from .prestador import Prestador
from .rps import RPS
from .pedido_cancelamento import PedidoCancelamentoNFSe
from .configuracao import Ambiente, Configuracao
2 changes: 2 additions & 0 deletions PyNFSe/utils/entidades/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

class Entidade(object):

def __init__(self, **kwargs):
Expand Down
Loading