Metadata-Version: 2.1
Name: nfsepmsj
Version: 0.0.2
Summary: Biblioteca para acesso ao Webservices de NFSe da Prefeitura Municipal de Sao Jose - SC
Home-page: https://github.com/qualitaocupacional/nfsepmsj
Author: Qualita Seguranca e Saude Ocupacional
Author-email: lab.ti@qualitaocupacional.com.br
License: Apache 2.0
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Requires-Dist: requests (>=2.7.0)
Requires-Dist: lxml (>=4.2.1)
Requires-Dist: zeep (>=2.5.0)
Requires-Dist: signxml (>=2.5.2)
Requires-Dist: pyOpenSSL (>=17.5.0)
Requires-Dist: six (>=1.11.0)

NFSe de São José - Santa Catarina
=================================

Biblioteca para auxiliar a assinar, gerar e consultar NFSe da Prefeitura Municipal de São José.
Padrão **ABRASF** da **Betha Software**.

Instalação
----------

A biblioteca está disponível no PyPi:

.. code::

    user@host:~$ pip install nfsepmsj

Desenvolvimento
---------------

Clonar o repositório:

.. code::

    user@host:~$ git clone https://github.com/qualitaocupacional/nfsepmsj.git

Instalar a lib em modo desenvolvimento:

.. code::

    (virtualenv) user@host:~/nfsepmsj$ pip install -e ".[testing]"

Usando
------

.. code:: python

    from nfsepmsj.client import NFSe

    pfx_file = '/caminho/do/arquivo.pfx'
    pfx_passwd = 'Senha do arquivo pfx'

    nfse = NFSe(pfx_file, pfx_passwd)
    nf_data = {
        'rps.lote.id': 'loteid',
        'nf.data.emissao': 'AAAA-MM-DD',
        'nf.total_nota': '100.30'
        # demais campos...
    }
    nfse.add_rps(data)
    result, errors = nfse.send()

*result* vai ser uma lista de dicionários com a estrutura:

.. code:: javascript

    [
        {
            'rps.lote.id': 'loteid',
            'xml.response': 'XML com a resposta do webservices',
            'xml': 'o XML que foi gerado para envio',
        }
    ]

E *errors*, se houver algum, como, por exemplo, erro de validação do XML, vai ser:

.. code:: javascript

    [
        {
            'rps.lote.id': 'loteid',
            'xml': 'o XML que foi gerado para envio',
            'error': 'a mensagem do erro'
        }
    ]

Estrutura do dicionário com os campos da nota fiscal:

+-------------------------------------+------------------------------+
| Nome                                | Descrição                    |
+=====================================+==============================+
| 'rps.lote.id'                       | Identificação única do lote  |
+-------------------------------------+------------------------------+
| 'rps.numero'                        |                              |
+-------------------------------------+------------------------------+
| 'rps.serie'                         |                              |
+-------------------------------------+------------------------------+
| 'rps.tipo'                          |                              |
+-------------------------------------+------------------------------+
| 'rps.data.emissao'                  |                              |
+-------------------------------------+------------------------------+
| 'rps.status'                        | 1-Normal, 2-Cancelado        |
+-------------------------------------+------------------------------+
| 'rps.substituido.numero'            |                              |
+-------------------------------------+------------------------------+
| 'rps.substituido.serie'             |                              |
+-------------------------------------+------------------------------+
| 'rps.substituido.tipo'              |                              |
+-------------------------------------+------------------------------+
| 'nf.data.emissao'                   |                              |
+-------------------------------------+------------------------------+
| 'nf.total_nota'                     |                              |
+-------------------------------------+------------------------------+
| 'nf.valor_deducoes'                 |                              |
+-------------------------------------+------------------------------+
| 'nf.valor_pis'                      |                              |
+-------------------------------------+------------------------------+
| 'nf.valor_cofins'                   |                              |
+-------------------------------------+------------------------------+
| 'nf.valor_inss'                     |                              |
+-------------------------------------+------------------------------+
| 'nf.valor_IR'                       |                              |
+-------------------------------------+------------------------------+
| 'nf.valor_csll'                     |                              |
+-------------------------------------+------------------------------+
| 'nf.valor_outros'                   |                              |
+-------------------------------------+------------------------------+
| 'nf.valor_iss'                      |                              |
+-------------------------------------+------------------------------+
| 'nf.aliquota'                       |                              |
+-------------------------------------+------------------------------+
| 'nf.desconto_incondicionado'        |                              |
+-------------------------------------+------------------------------+
| 'nf.desconto_condicionado'          |                              |
+-------------------------------------+------------------------------+
| 'nf.iss_retido'                     |                              |
+-------------------------------------+------------------------------+
| 'nf.responsavel_retencao'           |                              |
+-------------------------------------+------------------------------+
| 'nf.codigo_servico'                 |                              |
+-------------------------------------+------------------------------+
| 'nf.codigo_cnae'                    |                              |
+-------------------------------------+------------------------------+
| 'nf.codigo_tributacao_municipio'    |                              |
+-------------------------------------+------------------------------+
| 'nf.discriminacao'                  |                              |
+-------------------------------------+------------------------------+
| 'nf.codigo_municipio'               |                              |
+-------------------------------------+------------------------------+
| 'nf.codigo_pais'                    |                              |
+-------------------------------------+------------------------------+
| 'nf.exigibilidade_iss'              |                              |
+-------------------------------------+------------------------------+
| 'nf.codigo_municipio_incidencia'    |                              |
+-------------------------------------+------------------------------+
| 'nf.numero_processo'                |                              |
+-------------------------------------+------------------------------+
| 'nf.prestador.documento'            |                              |
+-------------------------------------+------------------------------+
| 'nf.prestador.inscricao_municipal'  |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.documento'              |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.inscricao_municipal'    |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.razao_social'           |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.logradouro'             |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.numero_logradouro'      |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.complemento'            |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.bairro'                 |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.codigo_municipio'       |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.uf'                     |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.codigo_pais'            |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.cep'                    |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.contato.telefone'       |                              |
+-------------------------------------+------------------------------+
| 'nf.tomador.contato.email'          |                              |
+-------------------------------------+------------------------------+
| 'nf.regime_especial_tributacao'     |                              |
+-------------------------------------+------------------------------+
| 'nf.optante_simples'                |                              |
+-------------------------------------+------------------------------+
| 'nf.incentivo_fiscal'               |                              |
+-------------------------------------+------------------------------+
| ...                                 | ...                          |
+-------------------------------------+------------------------------+

**TODO**: ainda falta os campos para *Intermediário* e *Construção Civil*.

Campos adicionais para **Cancelamento** de NFSe:

+-------------------------------------+--------------------------------------+
| Nome                                | Descrição                            |
+=====================================+======================================+
| 'nf.cancela.id'                     | Identificação única do cancelamento  |
+-------------------------------------+--------------------------------------+
| 'nf.numero'                         | Número da NFSe gerada                |
+-------------------------------------+--------------------------------------+
| 'nf.codigo_cancelamento'            | Código do cancelamento               |
+-------------------------------------+--------------------------------------+

O **Código do Cancelamento** é obrigatório, apesar que na documentação da versão **2.02** informar que esse código é opcional.
Sem esse código o webservices retorna **"Erro desconhecido"**.

Os valores possíveis são:

* 1 - Erro na emissão
* 2 - Serviço não prestado
* 3 - Erro de assinatura
* 4 - Duplicidade da nota
* 5 - Erro de processamento

Sendo que os códigos **3** e **5** são de uso restrito da Administração Tributária Municipal.

**Cancelando uma NFSe**

.. code:: python

    from nfsepmsj.client import NFSe

    pfx_file = '/caminho/do/arquivo.pfx'
    pfx_passwd = 'Senha do arquivo pfx'

    nfse = NFSe(pfx_file, pfx_passwd)
    cancel_data = {
        'nf.cancela.id': 'cancel_id1',
        'nf.codigo_cancelamento': '1',
        'nf.numero': '1',
        'nf.prestador.documento': '99999999999999',
        'nf.prestador.inscricao_municipal': '9999999',
        'nf.codigo_municipio': '4216602',
    }
    nfse.add_to_cancel(cancel_data)
    result, errors = nfse.cancel()

*result* vai ser uma lista de dicionários com a estrutura:

.. code:: javascript

    [
        {
            'nf.cancela.id': 'cancel_id1',
            'xml.response': 'XML com a resposta do webservices',
            'xml': 'o XML que foi gerado para envio',
        }
    ]

E *errors*, se houver algum, como, por exemplo, erro de validação do XML, vai ser:

.. code:: javascript

    [
        {
            'nf.cancela.id': 'cancel_id1',
            'xml': 'o XML que foi gerado para envio',
            'error': 'a mensagem do erro'
        }
    ]


Campos adicionais para **Envio em Lote** de NFSe:

+-------------------------------------+--------------------------------------+
| Nome                                | Descrição                            |
+=====================================+======================================+
| 'lote.id'                           | Identificação única do lote          |
+-------------------------------------+--------------------------------------+
| 'lote.numero'                       | Número do lote                       |
+-------------------------------------+--------------------------------------+
| 'nf.prestador.documento'            | CPF/CNPJ do prestador                |
+-------------------------------------+--------------------------------------+
| 'nf.prestador.inscricao_municipal'  | Inscrição municipal do prestador     |
+-------------------------------------+--------------------------------------+

Lembrando que nesta modalidade os dados de RPS devem conter os campos:

* 'rps.numero'
* 'rps.serie'
* 'rps.tipo'
* 'rps.data.emissao'
* 'rps.status'

**Enviando um lote (sincrono)**

.. code:: python

    from nfsepmsj.client import NFSe

    pfx_file = '/caminho/do/arquivo.pfx'
    pfx_passwd = 'Senha do arquivo pfx'

    nfse = NFSe(pfx_file, pfx_passwd)
    # ...

    nfse.add_rps(rps01_data)
    nfse.add_rps(rps02_data)
    # ...
    batch_data = {
        'lote.id': 'lote_id',
        'lote.numero': '201901',
        'nf.prestador.documento': '99999999999999',
        'nf.prestador.inscricao_municipal': '9999999',
    }
    result, errors = nfse.send_batch(batch_data)


*result* vai ser um dicionário com a estrutura:

.. code:: javascript

    {
        'lote.id': 'lote_id',
        'xml.response': 'XML com a resposta do webservices',
        'xml': 'o XML que foi gerado para envio',
    }

E *errors*, se houver algum, como, por exemplo, erro de validação do XML, vai ser:

.. code:: javascript

    {
        'lote.id': 'lote_id',
        'xml': 'o XML que foi gerado para envio',
        'error': 'a mensagem do erro'
    }



