simplesnacional 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- simplesnacional/__init__.py +361 -0
- simplesnacional-0.1.2.dist-info/METADATA +128 -0
- simplesnacional-0.1.2.dist-info/RECORD +7 -0
- simplesnacional-0.1.2.dist-info/WHEEL +5 -0
- simplesnacional-0.1.2.dist-info/entry_points.txt +2 -0
- simplesnacional-0.1.2.dist-info/licenses/LICENSE +21 -0
- simplesnacional-0.1.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
import xml.etree.ElementTree as ET
|
|
4
|
+
import zipfile
|
|
5
|
+
import os
|
|
6
|
+
import sqlite3
|
|
7
|
+
import csv
|
|
8
|
+
import argparse
|
|
9
|
+
import re
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn, TimeRemainingColumn, TransferSpeedColumn
|
|
12
|
+
from rich.panel import Panel
|
|
13
|
+
from rich.table import Table
|
|
14
|
+
|
|
15
|
+
console = Console()
|
|
16
|
+
|
|
17
|
+
BASE_URL = "https://arquivos.receitafederal.gov.br"
|
|
18
|
+
SHARE_TOKEN = "YggdBLfdninEJX9"
|
|
19
|
+
WEBDAV_URL = f"{BASE_URL}/public.php/webdav"
|
|
20
|
+
DAV_FILES_URL = f"{BASE_URL}/public.php/dav/files/{SHARE_TOKEN}"
|
|
21
|
+
DAV_NS = {"d": "DAV:"}
|
|
22
|
+
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
|
|
23
|
+
|
|
24
|
+
class DadosSimples:
|
|
25
|
+
def __init__(self, data):
|
|
26
|
+
self.cnpj_base = data[0]
|
|
27
|
+
self.opcao_simples = data[1]
|
|
28
|
+
self.data_opcao_simples = self._format_date(data[2])
|
|
29
|
+
self.data_exclusao_simples = self._format_date(data[3])
|
|
30
|
+
self.opcao_mei = data[4]
|
|
31
|
+
self.data_opcao_mei = self._format_date(data[5])
|
|
32
|
+
self.data_exclusao_mei = self._format_date(data[6])
|
|
33
|
+
|
|
34
|
+
def _format_date(self, date_str):
|
|
35
|
+
if date_str and len(str(date_str)) == 8 and str(date_str).isdigit():
|
|
36
|
+
date_str = str(date_str)
|
|
37
|
+
return f"{date_str[6:8]}/{date_str[4:6]}/{date_str[0:4]}"
|
|
38
|
+
return date_str
|
|
39
|
+
|
|
40
|
+
def __repr__(self):
|
|
41
|
+
return f"<DadosSimples(cnpj={self.cnpj_base}, simples={self.opcao_simples}, mei={self.opcao_mei})>"
|
|
42
|
+
|
|
43
|
+
def get_db_paths():
|
|
44
|
+
target_dir_tmp = os.path.join(os.path.expanduser("~"), ".simples", "tmp")
|
|
45
|
+
db_path = os.path.join(os.path.expanduser("~"), ".simples", "simples.db")
|
|
46
|
+
return target_dir_tmp, db_path
|
|
47
|
+
|
|
48
|
+
def consulta(cnpj):
|
|
49
|
+
# Limpar CNPJ e pegar os 8 primeiros dígitos
|
|
50
|
+
clean_cnpj = re.sub(r'\D', '', str(cnpj))
|
|
51
|
+
cnpj_base = clean_cnpj[:8]
|
|
52
|
+
|
|
53
|
+
_, db_path = get_db_paths()
|
|
54
|
+
|
|
55
|
+
if not os.path.exists(db_path):
|
|
56
|
+
console.print("[red]Banco de dados não encontrado. Execute 'simplesnacional atualizar' primeiro.[/]")
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
conn = sqlite3.connect(db_path)
|
|
60
|
+
cursor = conn.cursor()
|
|
61
|
+
|
|
62
|
+
cursor.execute("SELECT * FROM SIMPLES WHERE CNPJ_BASE = ?", (cnpj_base,))
|
|
63
|
+
result = cursor.fetchone()
|
|
64
|
+
conn.close()
|
|
65
|
+
|
|
66
|
+
if result:
|
|
67
|
+
return DadosSimples(result)
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
def info():
|
|
71
|
+
_, db_path = get_db_paths()
|
|
72
|
+
if not os.path.exists(db_path):
|
|
73
|
+
console.print("[red]Banco de dados não encontrado.[/]")
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
conn = sqlite3.connect(db_path)
|
|
77
|
+
cursor = conn.cursor()
|
|
78
|
+
|
|
79
|
+
# Pegar metadados
|
|
80
|
+
cursor.execute("SELECT DATA_BASE FROM METADATA ORDER BY ROWID DESC LIMIT 1")
|
|
81
|
+
meta = cursor.fetchone()
|
|
82
|
+
data_base = meta[0] if meta else "Desconhecida"
|
|
83
|
+
|
|
84
|
+
# Contar registros (pode ser lento, usar COUNT *)
|
|
85
|
+
try:
|
|
86
|
+
cursor.execute("SELECT Count(*) FROM SIMPLES")
|
|
87
|
+
count = cursor.fetchone()[0]
|
|
88
|
+
except:
|
|
89
|
+
count = 0
|
|
90
|
+
|
|
91
|
+
conn.close()
|
|
92
|
+
|
|
93
|
+
panel = Panel(
|
|
94
|
+
f"Data Base: [bold cyan]{data_base}[/]\n"
|
|
95
|
+
f"Total de CNPJs: [bold green]{count:,}[/]",
|
|
96
|
+
title="Simples Nacional Info"
|
|
97
|
+
)
|
|
98
|
+
console.print(panel)
|
|
99
|
+
|
|
100
|
+
def db_init():
|
|
101
|
+
_, db_path = get_db_paths()
|
|
102
|
+
target_dir = os.path.dirname(db_path)
|
|
103
|
+
os.makedirs(target_dir, exist_ok=True)
|
|
104
|
+
|
|
105
|
+
console.print("[cyan]Inicializando banco de dados...[/]")
|
|
106
|
+
conn = sqlite3.connect(db_path)
|
|
107
|
+
cursor = conn.cursor()
|
|
108
|
+
cursor.executescript('''
|
|
109
|
+
DROP TABLE IF EXISTS SIMPLES;
|
|
110
|
+
DROP TABLE IF EXISTS METADATA;
|
|
111
|
+
CREATE TABLE SIMPLES (
|
|
112
|
+
CNPJ_BASE TEXT PRIMARY KEY,
|
|
113
|
+
OPCAO_SIMPLES TEXT,
|
|
114
|
+
DATA_OPCAO_SIMPLES TEXT,
|
|
115
|
+
DATA_EXCLUSAO_SIMPLES TEXT,
|
|
116
|
+
OPCAO_MEI TEXT,
|
|
117
|
+
DATA_OPCAO_MEI TEXT,
|
|
118
|
+
DATA_EXCLUSAO_MEI TEXT
|
|
119
|
+
);
|
|
120
|
+
CREATE TABLE METADATA (
|
|
121
|
+
DATA_BASE TEXT,
|
|
122
|
+
DATA_DOWNLOAD TEXT
|
|
123
|
+
);
|
|
124
|
+
''')
|
|
125
|
+
conn.commit()
|
|
126
|
+
conn.close()
|
|
127
|
+
console.print("[green]Banco de dados recriado.[/]")
|
|
128
|
+
|
|
129
|
+
def parse_csv(version_date):
|
|
130
|
+
target_dir, db_path = get_db_paths()
|
|
131
|
+
|
|
132
|
+
# Encontrar arquivo
|
|
133
|
+
try:
|
|
134
|
+
arquivos = os.listdir(target_dir)
|
|
135
|
+
arquivo_nome = [f for f in arquivos if "SIMPLES" in f][0]
|
|
136
|
+
csv_path = os.path.join(target_dir, arquivo_nome)
|
|
137
|
+
except (IndexError, FileNotFoundError):
|
|
138
|
+
console.print("[bold red]Nenhum arquivo CSV 'Simples' encontrado em:[/]")
|
|
139
|
+
console.print(f"[red]{target_dir}[/]")
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
conn = sqlite3.connect(db_path)
|
|
143
|
+
cursor = conn.cursor()
|
|
144
|
+
|
|
145
|
+
cursor.execute("PRAGMA synchronous = OFF")
|
|
146
|
+
cursor.execute("PRAGMA journal_mode = MEMORY")
|
|
147
|
+
|
|
148
|
+
file_size = os.path.getsize(csv_path)
|
|
149
|
+
batch_size = 100000
|
|
150
|
+
batch = []
|
|
151
|
+
|
|
152
|
+
query = '''
|
|
153
|
+
INSERT OR REPLACE INTO SIMPLES (
|
|
154
|
+
CNPJ_BASE, OPCAO_SIMPLES, DATA_OPCAO_SIMPLES, DATA_EXCLUSAO_SIMPLES,
|
|
155
|
+
OPCAO_MEI, DATA_OPCAO_MEI, DATA_EXCLUSAO_MEI
|
|
156
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
157
|
+
'''
|
|
158
|
+
|
|
159
|
+
with Progress(
|
|
160
|
+
SpinnerColumn(),
|
|
161
|
+
TextColumn("[progress.description]{task.description}"),
|
|
162
|
+
BarColumn(),
|
|
163
|
+
TransferSpeedColumn(),
|
|
164
|
+
TimeRemainingColumn(),
|
|
165
|
+
console=console
|
|
166
|
+
) as progress:
|
|
167
|
+
task = progress.add_task("[green]Importando para o banco de dados...", total=file_size)
|
|
168
|
+
|
|
169
|
+
with open(csv_path, 'r', encoding='latin-1') as f:
|
|
170
|
+
def file_reader_generator():
|
|
171
|
+
processed_bytes = 0
|
|
172
|
+
last_update = 0
|
|
173
|
+
for line in f:
|
|
174
|
+
yield line
|
|
175
|
+
processed_bytes += len(line) + 1
|
|
176
|
+
if processed_bytes - last_update > 1024 * 1024:
|
|
177
|
+
progress.update(task, completed=processed_bytes)
|
|
178
|
+
last_update = processed_bytes
|
|
179
|
+
progress.update(task, completed=processed_bytes)
|
|
180
|
+
|
|
181
|
+
reader = csv.reader(file_reader_generator(), delimiter=';', quotechar='"')
|
|
182
|
+
for row in reader:
|
|
183
|
+
if len(row) == 7:
|
|
184
|
+
batch.append(row)
|
|
185
|
+
if len(batch) >= batch_size:
|
|
186
|
+
cursor.executemany(query, batch)
|
|
187
|
+
conn.commit()
|
|
188
|
+
batch = []
|
|
189
|
+
if batch:
|
|
190
|
+
cursor.executemany(query, batch)
|
|
191
|
+
conn.commit()
|
|
192
|
+
|
|
193
|
+
console.print("[cyan]Criando índice no banco de dados...[/]")
|
|
194
|
+
cursor.execute("CREATE INDEX IF NOT EXISTS idx_cnpj_base ON SIMPLES (CNPJ_BASE ASC)")
|
|
195
|
+
conn.commit()
|
|
196
|
+
|
|
197
|
+
console.print("[cyan]Atualizando metadados...[/]")
|
|
198
|
+
cursor.execute("INSERT INTO METADATA (DATA_BASE, DATA_DOWNLOAD) VALUES (?, ?)",
|
|
199
|
+
(version_date.strftime('%Y-%m-%d %H:%M:%S'), datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
|
|
200
|
+
conn.commit()
|
|
201
|
+
conn.close()
|
|
202
|
+
console.print("[bold green]Importação concluída com sucesso![/]")
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
os.remove(csv_path)
|
|
206
|
+
console.print(f"[green]Arquivo temporário removido: {arquivo_nome}[/]")
|
|
207
|
+
except OSError as e:
|
|
208
|
+
console.print(f"[red]Erro ao remover arquivo temporário: {e}[/]")
|
|
209
|
+
|
|
210
|
+
def get_local_version():
|
|
211
|
+
_, db_path = get_db_paths()
|
|
212
|
+
if not os.path.exists(db_path):
|
|
213
|
+
return None
|
|
214
|
+
try:
|
|
215
|
+
conn = sqlite3.connect(db_path)
|
|
216
|
+
cursor = conn.cursor()
|
|
217
|
+
cursor.execute("SELECT DATA_BASE FROM METADATA ORDER BY ROWID DESC LIMIT 1")
|
|
218
|
+
result = cursor.fetchone()
|
|
219
|
+
conn.close()
|
|
220
|
+
if result:
|
|
221
|
+
return datetime.strptime(result[0], '%Y-%m-%d %H:%M:%S')
|
|
222
|
+
except Exception:
|
|
223
|
+
return None
|
|
224
|
+
return None
|
|
225
|
+
|
|
226
|
+
def listar_versoes_disponiveis():
|
|
227
|
+
headers = {"Depth": "1", "User-Agent": USER_AGENT}
|
|
228
|
+
response = requests.request(
|
|
229
|
+
"PROPFIND", f"{WEBDAV_URL}/", auth=(SHARE_TOKEN, ""),
|
|
230
|
+
headers=headers, timeout=60
|
|
231
|
+
)
|
|
232
|
+
response.raise_for_status()
|
|
233
|
+
|
|
234
|
+
root = ET.fromstring(response.content)
|
|
235
|
+
versoes = []
|
|
236
|
+
for item in root.findall("d:response", DAV_NS):
|
|
237
|
+
href = item.find("d:href", DAV_NS).text
|
|
238
|
+
match = re.search(r"(\d{4})-(\d{2})/?$", href)
|
|
239
|
+
if match:
|
|
240
|
+
versoes.append(f"{match.group(1)}-{match.group(2)}")
|
|
241
|
+
return sorted(set(versoes))
|
|
242
|
+
|
|
243
|
+
def atualizar():
|
|
244
|
+
with Progress(
|
|
245
|
+
SpinnerColumn(),
|
|
246
|
+
TextColumn("[progress.description]{task.description}"),
|
|
247
|
+
BarColumn(),
|
|
248
|
+
TransferSpeedColumn(),
|
|
249
|
+
TimeRemainingColumn(),
|
|
250
|
+
console=console
|
|
251
|
+
) as progress:
|
|
252
|
+
|
|
253
|
+
task_check = progress.add_task("[cyan]Verificando atualizações...", total=None)
|
|
254
|
+
|
|
255
|
+
try:
|
|
256
|
+
versoes = listar_versoes_disponiveis()
|
|
257
|
+
except Exception as e:
|
|
258
|
+
progress.update(task_check, completed=True)
|
|
259
|
+
console.print(f"[red]Erro ao conectar com a Receita Federal: {e}[/]")
|
|
260
|
+
return
|
|
261
|
+
|
|
262
|
+
progress.update(task_check, completed=True)
|
|
263
|
+
|
|
264
|
+
if not versoes:
|
|
265
|
+
console.print("[red]Nenhuma versão encontrada no servidor da Receita Federal.[/]")
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
ano_mes = versoes[-1]
|
|
269
|
+
site_date = datetime.strptime(ano_mes, "%Y-%m")
|
|
270
|
+
local_date = get_local_version()
|
|
271
|
+
|
|
272
|
+
console.print(Panel(
|
|
273
|
+
f"Data Disponibilização (Site): [bold green]{ano_mes}[/]\n"
|
|
274
|
+
f"Data Base Local: [bold yellow]{local_date if local_date else 'Inexistente'}[/]",
|
|
275
|
+
title="Status de Versão"
|
|
276
|
+
))
|
|
277
|
+
|
|
278
|
+
if local_date is not None and site_date <= local_date:
|
|
279
|
+
console.print(f"[bold blue]O banco de dados já está atualizado.[/]")
|
|
280
|
+
return
|
|
281
|
+
|
|
282
|
+
console.print("[bold green]Nova versão disponível ou banco inexistente. Iniciando atualização...[/]")
|
|
283
|
+
|
|
284
|
+
url_zip = f"{DAV_FILES_URL}/{ano_mes}/Simples.zip"
|
|
285
|
+
response = requests.get(url_zip, headers={"User-Agent": USER_AGENT}, stream=True, timeout=60)
|
|
286
|
+
total_size = int(response.headers.get('content-length', 0))
|
|
287
|
+
|
|
288
|
+
if response.status_code == 200:
|
|
289
|
+
target_dir, _ = get_db_paths()
|
|
290
|
+
os.makedirs(target_dir, exist_ok=True)
|
|
291
|
+
zip_path = os.path.join(target_dir, "Simples.zip")
|
|
292
|
+
|
|
293
|
+
task_download = progress.add_task("[green]Baixando arquivo...", total=total_size)
|
|
294
|
+
|
|
295
|
+
with open(zip_path, "wb") as file:
|
|
296
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
297
|
+
file.write(chunk)
|
|
298
|
+
progress.update(task_download, advance=len(chunk))
|
|
299
|
+
|
|
300
|
+
console.print("[green]Arquivo baixado com sucesso.[/]")
|
|
301
|
+
|
|
302
|
+
task_extract = progress.add_task("[yellow]Descompactando...", total=None)
|
|
303
|
+
with zipfile.ZipFile(zip_path, "r") as zip_ref:
|
|
304
|
+
zip_ref.extractall(target_dir)
|
|
305
|
+
progress.update(task_extract, completed=True)
|
|
306
|
+
|
|
307
|
+
console.print(f"[green]Arquivo descompactado com sucesso em: {target_dir}[/]")
|
|
308
|
+
os.remove(zip_path)
|
|
309
|
+
console.print("[green]Arquivo removido com sucesso.[/]")
|
|
310
|
+
|
|
311
|
+
db_init()
|
|
312
|
+
parse_csv(site_date)
|
|
313
|
+
|
|
314
|
+
else:
|
|
315
|
+
console.print(f"[bold red]Erro ao baixar o arquivo. Status code: {response.status_code}[/]")
|
|
316
|
+
|
|
317
|
+
def cli():
|
|
318
|
+
parser = argparse.ArgumentParser(description="Gestor do Simples Nacional")
|
|
319
|
+
subparsers = parser.add_subparsers(dest="command", help="Comandos disponíveis")
|
|
320
|
+
|
|
321
|
+
# Comando: consultar
|
|
322
|
+
parser_consultar = subparsers.add_parser("consultar", help="Consulta um CNPJ na base de dados")
|
|
323
|
+
parser_consultar.add_argument("cnpj", help="CNPJ para consulta (apenas números ou formatado)")
|
|
324
|
+
|
|
325
|
+
# Comando: atualizar
|
|
326
|
+
subparsers.add_parser("atualizar", help="Verifica e atualiza a base de dados")
|
|
327
|
+
|
|
328
|
+
# Comando: info
|
|
329
|
+
subparsers.add_parser("info", help="Exibe informações sobre a base de dados local")
|
|
330
|
+
|
|
331
|
+
args = parser.parse_args()
|
|
332
|
+
|
|
333
|
+
if args.command == "consultar":
|
|
334
|
+
dados = consulta(args.cnpj)
|
|
335
|
+
if dados:
|
|
336
|
+
table = Table(title=f"Dados do CNPJ: {dados.cnpj_base}")
|
|
337
|
+
table.add_column("Campo", justify="right", style="cyan", no_wrap=True)
|
|
338
|
+
table.add_column("Valor", style="magenta")
|
|
339
|
+
|
|
340
|
+
table.add_row("Opção Simples", dados.opcao_simples)
|
|
341
|
+
table.add_row("Data Opção Simples", dados.data_opcao_simples)
|
|
342
|
+
table.add_row("Data Exclusão Simples", dados.data_exclusao_simples)
|
|
343
|
+
table.add_row("Opção MEI", dados.opcao_mei)
|
|
344
|
+
table.add_row("Data Opção MEI", dados.data_opcao_mei)
|
|
345
|
+
table.add_row("Data Exclusão MEI", dados.data_exclusao_mei)
|
|
346
|
+
|
|
347
|
+
console.print(table)
|
|
348
|
+
else:
|
|
349
|
+
console.print(f"[red]CNPJ {args.cnpj} não encontrado na base.[/]")
|
|
350
|
+
|
|
351
|
+
elif args.command == "atualizar":
|
|
352
|
+
atualizar()
|
|
353
|
+
|
|
354
|
+
elif args.command == "info":
|
|
355
|
+
info()
|
|
356
|
+
|
|
357
|
+
else:
|
|
358
|
+
parser.print_help()
|
|
359
|
+
|
|
360
|
+
if __name__ == "__main__":
|
|
361
|
+
cli()
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simplesnacional
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Biblioteca e CLI para consulta e atualização da base de dados do Simples Nacional.
|
|
5
|
+
Author: David Silva
|
|
6
|
+
Author-email: David Silva <david.emery.silva@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: requests
|
|
15
|
+
Requires-Dist: rich
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
Dynamic: requires-python
|
|
19
|
+
|
|
20
|
+
# Simples Nacional Lib
|
|
21
|
+
<div align="center">
|
|
22
|
+
<img alt="image" src="https://github.com/user-attachments/assets/b4a11a93-2f85-431c-86d9-ed0f647f241f" />
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<img src="https://static.pepy.tech/badge/simplesnacional" />
|
|
27
|
+
<img src="https://img.shields.io/pypi/v/simplesnacional" />
|
|
28
|
+
<img src="https://img.shields.io/github/stars/DaavidSiilva/simplesnacional" />
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
Biblioteca e CLI em Python para consulta e atualização da base de dados pública do Simples Nacional (CNPJs).
|
|
33
|
+
|
|
34
|
+
## Instalação
|
|
35
|
+
|
|
36
|
+
Para instalar a biblioteca localmente:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install .
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Uso via Linha de Comando (CLI)
|
|
43
|
+
|
|
44
|
+
Após a instalação, o comando `simplesnacional` estará disponível no seu terminal.
|
|
45
|
+
|
|
46
|
+
### 1. Atualizar a Base de Dados
|
|
47
|
+
Antes de realizar consultas, é necessário baixar e atualizar a base de dados local. O comando abaixo verifica se existe uma nova versão no site da Receita Federal e realiza o download e importação se necessário.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
simplesnacional atualizar
|
|
51
|
+
```
|
|
52
|
+
Este processo pode demorar alguns minutos dependendo da velocidade da internet e do processamento, pois a base é volumosa.
|
|
53
|
+
|
|
54
|
+
### 2. Verificar Status
|
|
55
|
+
Para ver informações sobre a base de dados local, como a data de referência e o total de registros importados:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
simplesnacional info
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. Consultar um CNPJ
|
|
62
|
+
Para consultar os dados do Simples Nacional de um CNPJ específico:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
simplesnacional consultar 00000000000191
|
|
66
|
+
```
|
|
67
|
+
Ou com formatação:
|
|
68
|
+
```bash
|
|
69
|
+
simplesnacional consultar 00.000.000/0001-91
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Saída Exemplo:**
|
|
73
|
+
```text
|
|
74
|
+
Dados do CNPJ: 00000000
|
|
75
|
+
+-----------------------+------------+
|
|
76
|
+
| Campo | Valor |
|
|
77
|
+
+-----------------------+------------+
|
|
78
|
+
| Opção Simples | S |
|
|
79
|
+
| Data Opção Simples | 20070701 |
|
|
80
|
+
| Data Exclusão Simples | |
|
|
81
|
+
| Opção MEI | N |
|
|
82
|
+
| Data Opção MEI | |
|
|
83
|
+
| Data Exclusão MEI | |
|
|
84
|
+
+-----------------------+------------+
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Uso como Biblioteca Python
|
|
88
|
+
|
|
89
|
+
Você pode utilizar a biblioteca diretamente em seu código Python para realizar consultas.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from simplesnacional import consulta
|
|
93
|
+
|
|
94
|
+
# Realizar a consulta
|
|
95
|
+
# O CNPJ pode ser passado como string (com ou sem pontuação) ou inteiro
|
|
96
|
+
dados = consulta("00.000.000/0001-91")
|
|
97
|
+
|
|
98
|
+
if dados:
|
|
99
|
+
print(f"CNPJ Base: {dados.cnpj_base}")
|
|
100
|
+
print(f"Optante Simples: {dados.opcao_simples}")
|
|
101
|
+
print(f"Data Opção: {dados.data_opcao_simples}")
|
|
102
|
+
print(f"Optante MEI: {dados.opcao_mei}")
|
|
103
|
+
else:
|
|
104
|
+
print("CNPJ não encontrado na base local.")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Estrutura do Objeto Retornado
|
|
108
|
+
A função `consulta` retorna um objeto `DadosSimples` com os seguintes atributos:
|
|
109
|
+
|
|
110
|
+
- `cnpj_base`: Os 8 primeiros dígitos do CNPJ
|
|
111
|
+
- `opcao_simples`: Indicador de opção pelo Simples ('S' ou 'N')
|
|
112
|
+
- `data_opcao_simples`: Data da opção pelo Simples
|
|
113
|
+
- `data_exclusao_simples`: Data da exclusão do Simples (se houver)
|
|
114
|
+
- `opcao_mei`: Indicador de opção pelo MEI ('S' ou 'N')
|
|
115
|
+
- `data_opcao_mei`: Data da opção pelo MEI
|
|
116
|
+
- `data_exclusao_mei`: Data da exclusão do MEI (se houver)
|
|
117
|
+
|
|
118
|
+
## Licença
|
|
119
|
+
|
|
120
|
+
MIT License
|
|
121
|
+
|
|
122
|
+
### Aviso Legal e Isenção de Responsabilidade
|
|
123
|
+
|
|
124
|
+
Este software é um projeto **independente e de código aberto**.
|
|
125
|
+
|
|
126
|
+
Esta biblioteca e CLI **não possuem qualquer vínculo, afiliação, endosso ou parceria** com a Receita Federal do Brasil ou qualquer outra entidade governamental.
|
|
127
|
+
|
|
128
|
+
O objetivo deste projeto é estritamente facilitar o acesso técnico e a consulta automatizada à base de dados pública do Simples Nacional. Embora a ferramenta utilize dados públicos oficiais, ela não substitui os canais oficiais de consulta para fins legais, fiscais ou tributários.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
simplesnacional/__init__.py,sha256=YmdC-NN09vwJvaeEb8JlP4ohx0XAgd-D2Y2QGgZvI_0,13127
|
|
2
|
+
simplesnacional-0.1.2.dist-info/licenses/LICENSE,sha256=X9c1jajPsNot8rYaj1Bq1Q8yBtJqttGAvzmim-BMd7s,1098
|
|
3
|
+
simplesnacional-0.1.2.dist-info/METADATA,sha256=BmT8wfXnaqy2vsj9eRXMzpuhpk4p4YTZbjw5Dol5yPA,4379
|
|
4
|
+
simplesnacional-0.1.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
5
|
+
simplesnacional-0.1.2.dist-info/entry_points.txt,sha256=u9a3UFJSnry5VeuNGSTnooKwLsR7UjQWfrXyrE11F8c,56
|
|
6
|
+
simplesnacional-0.1.2.dist-info/top_level.txt,sha256=7_IHo07MtxNSKQN4yZ-ZkSFfnOElyXPw8LYDMtyfRwI,16
|
|
7
|
+
simplesnacional-0.1.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Simples Nacional Lib
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
simplesnacional
|