diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fd44c9..53a85cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: jobs: check: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 permissions: contents: read strategy: diff --git a/README.md b/README.md index 52a9e22..2cae3af 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # FiscalAPI — SDK Python -Cliente Python da [FiscalAPI](https://fiscalapi.com.br): Inscrição Estadual nos 27 estados, CNPJ, certidões (CND estadual, CND Federal, CNDT, CRF/FGTS), XML de NF-e por chave, SIGEF, CNIR e perfil do produtor rural. +Cliente Python da [FiscalAPI](https://fiscalapi.com.br): Inscrição Estadual nos 27 estados, CNPJ, certidões (CND estadual, CND Federal, CNDT, CRF/FGTS), XML de NF-e por chave, NFS-e por chave, Simples Nacional, SIGEF, CNIR e perfil do produtor rural. - Zero dependências (só a biblioteca padrão). - Python 3.9 ou superior. @@ -44,6 +44,8 @@ for ie in resp["results"]: | `consultar_cndt(cpf=/cnpj=)` | `GET /api/consultar-cndt` | Certidão de débitos trabalhistas | | `consultar_crf_fgts(cpf=/cnpj=)` | `GET /api/consultar-crf-fgts` | Regularidade do FGTS | | `consultar_certidoes_todas(cpf=/cnpj=, skip_estaduais=False)` | `GET /api/certidoes-todas` | Todas as certidões em uma chamada | +| `consultar_simples_nacional(cnpj)` | `GET /api/consultar-simples-nacional` | Situação no Simples Nacional e SIMEI | +| `consultar_nfse(chave, danfse=False)` | `GET /api/consultar-nfse` | NFS-e (padrão nacional) por chave, sem certificado | | `consultar_nfe_xml(chave, certificado=, senha=, manifestar=True)` | `POST /api/consultar-nfe-xml` | XML completo da NF-e | | `consultar_sigef(cpf=/cnpj=)` | `GET /api/consultar-sigef` | Parcelas certificadas no SIGEF/INCRA | | `consultar_sigef_parcela(uuid, force_fresh=False)` | `GET /api/consultar-sigef-parcela` | Uma parcela com polígono, vértices e confrontantes | @@ -75,6 +77,25 @@ print(empresa["result"]["razao_social"], empresa["result"]["situacao_cadastral"] api.consultar_cnpj("12345678000195", force_fresh=True) ``` +### Simples Nacional + +```python +r = api.consultar_simples_nacional("11222333000181") +print(r["optante_simples"], r["situacao_simei"], r["regime_regular_ibs"]) +``` + +### NFS-e por chave + +```python +nfse = api.consultar_nfse( + "35503082211222333000181000000000012326100000045676", + danfse=True, # opcional: PDF do DANFSe em base64 +) +print(nfse["emitente"]["razao_social"], nfse["tributacao_municipal"]["valor_servico"]) +``` + +Uma consulta nova leva de 30 a 60 segundos. Só a NFS-e entregue é cobrada. + ### Certidões com PDF ```python diff --git a/pyproject.toml b/pyproject.toml index f3c5d86..a372e80 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "fiscalapi-br" -version = "0.1.1" +version = "0.2.0" description = "SDK da FiscalAPI (Brasil): Inscrição Estadual, CNPJ, certidões, NF-e, SIGEF, CNIR e perfil do produtor rural." readme = "README.md" license = "MIT" diff --git a/src/fiscalapi_br/_client.py b/src/fiscalapi_br/_client.py index 21c3b48..03beea1 100644 --- a/src/fiscalapi_br/_client.py +++ b/src/fiscalapi_br/_client.py @@ -31,9 +31,11 @@ ConsultaIEResponse, ConsultaIETodosResponse, NfeXmlResponse, + NfseResponse, PerfilProdutorResponse, SigefParcelaResponse, SigefResponse, + SimplesNacionalResponse, ) DEFAULT_BASE_URL = "https://api.fiscalapi.com.br" @@ -139,6 +141,15 @@ def consultar_cnpj(self, cnpj: str, *, force_fresh: bool = False) -> CNPJRespons params = {"cnpj": cnpj, "force_fresh": force_fresh or None} return cast(CNPJResponse, self._get("/api/consultar-cnpj", params)) + def consultar_simples_nacional(self, cnpj: str) -> SimplesNacionalResponse: + """Situação no Simples Nacional e SIMEI (``GET /api/consultar-simples-nacional``).""" + if not cnpj or not cnpj.strip(): + raise ValueError("Informe o CNPJ.") + return cast( + SimplesNacionalResponse, + self._get("/api/consultar-simples-nacional", {"cnpj": cnpj.strip()}), + ) + # ----------------------------------------------------------- Certidões def consultar_cnd( @@ -230,6 +241,18 @@ def consultar_nfe_xml( # POST não é repetido em 5xx: a manifestação pode já ter sido registrada. return cast(NfeXmlResponse, self._request("POST", "/api/consultar-nfe-xml", json_body=body)) + def consultar_nfse(self, chave: str, *, danfse: bool = False) -> NfseResponse: + """NFS-e (padrão nacional) pela chave de acesso, sem certificado (``GET /api/consultar-nfse``). + + ``danfse=True`` inclui o PDF do DANFSe em base64. Uma consulta nova + pode levar de 30 a 60 segundos. + """ + digitos = "".join(c for c in (chave or "") if c.isdigit()) + if not digitos: + raise ValueError("Informe a chave de acesso.") + params = {"chave": digitos, "danfse": danfse or None} + return cast(NfseResponse, self._get("/api/consultar-nfse", params)) + # ------------------------------------------------------- Imóvel rural def consultar_sigef( diff --git a/src/fiscalapi_br/_version.py b/src/fiscalapi_br/_version.py index 485f44a..d3ec452 100644 --- a/src/fiscalapi_br/_version.py +++ b/src/fiscalapi_br/_version.py @@ -1 +1 @@ -__version__ = "0.1.1" +__version__ = "0.2.0" diff --git a/src/fiscalapi_br/types.py b/src/fiscalapi_br/types.py index cbeade1..f6067de 100644 --- a/src/fiscalapi_br/types.py +++ b/src/fiscalapi_br/types.py @@ -248,3 +248,125 @@ class PerfilProdutorResponse(TypedDict, total=False): cnd_estaduais: Optional[CNDTodosResponse] certidoes_federais: List[CertidaoFederalResponse] cnir: Optional[CnirResponse] + + +class SimplesNacionalEventoFuturo(TypedDict, total=False): + regime: str + descricao: str + data_efeito: str + + +class SimplesNacionalPeriodoAnterior(TypedDict, total=False): + data_inicial: str + data_final: str + detalhamento: str + + +class SimplesNacionalMaisInfo(TypedDict, total=False): + opcoes_periodos_anteriores: str + opcoes_periodos_anteriores_lista: List[SimplesNacionalPeriodoAnterior] + enquadramentos_simei_periodos_anteriores: str + enquadramentos_simei_periodos_anteriores_lista: List[SimplesNacionalPeriodoAnterior] + eventos_futuros_simples: str + eventos_futuros_simei: str + mei_tac: str + + +class SimplesNacionalResponse(TypedDict, total=False): + request_id: str + cnpj: str + cnpj_matriz: str # para filiais, a situação é a da matriz + nome_empresarial: str + data_consulta: str + situacao_simples: str + optante_simples: bool + data_opcao_simples: Optional[str] + situacao_simei: str + enquadrado_simei: bool + regime_regular_ibs: str + regime_regular_cbs: str + eventos_futuros: List[SimplesNacionalEventoFuturo] + mais_info: Optional[SimplesNacionalMaisInfo] + cached: bool + + +class NfseEndereco(TypedDict, total=False): + logradouro: Optional[str] + numero: Optional[str] + complemento: Optional[str] + bairro: Optional[str] + cep: Optional[str] + municipio: Optional[str] + uf: Optional[str] + + +class NfseEmitente(TypedDict, total=False): + razao_social: Optional[str] + cpf_cnpj: Optional[str] + inscricao_municipal: Optional[str] + situacao_simples_nacional: Optional[str] + regime_especial_tributacao: Optional[str] + endereco: Optional[NfseEndereco] + + +class NfsePessoa(TypedDict, total=False): + cpf_cnpj: Optional[str] + inscricao_municipal: Optional[str] + nome: Optional[str] + + +class NfseServico(TypedDict, total=False): + pais: Optional[str] + municipio: Optional[str] + codigo_tributacao_nacional: Optional[str] + descricao_codigo: Optional[str] + item_nbs: Optional[str] + descricao: Optional[str] + + +class NfseTributacaoMunicipal(TypedDict, total=False): + tributacao_issqn: Optional[str] + municipio_incidencia: Optional[str] + valor_servico: Optional[float] + desconto_incondicionado: Optional[float] + deducoes: Optional[float] + beneficio_municipal: Optional[float] + base_calculo: Optional[float] + aliquota: Optional[float] # percentual (2.5 = 2,5%) + valor_issqn: Optional[float] + retencao: Optional[str] + + +class NfseTributacaoFederal(TypedDict, total=False): + situacao_pis_cofins: Optional[str] + base_calculo_pis_cofins: Optional[float] + aliquota_pis: Optional[float] + valor_pis: Optional[float] + aliquota_cofins: Optional[float] + valor_cofins: Optional[float] + irrf: Optional[float] + contribuicoes_sociais_retidas: Optional[float] + contribuicao_previdenciaria_retida: Optional[float] + + +class NfseResponse(TypedDict, total=False): + request_id: str + chave: str + numero_nfse: Optional[str] + codigo_municipio_emissor: Optional[str] + data_geracao: Optional[str] + versao: Optional[str] + dps: Optional[dict] + situacao: Optional[dict] # codigo/descricao; não indica cancelamento + emitente: Optional[NfseEmitente] + tomador: Optional[NfsePessoa] + intermediario: Optional[NfsePessoa] + servico: Optional[NfseServico] + tributacao_municipal: Optional[NfseTributacaoMunicipal] + tributacao_federal: Optional[NfseTributacaoFederal] + total_tributos: List[dict] + informacoes_complementares: Optional[str] + ambiente_gerador: Optional[str] + cached: bool + danfse_pdf_base64: Optional[str] # só com danfse=True + aviso: Optional[str]