libretificacaotjcore 0.1.0__tar.gz

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.

Potentially problematic release.


This version of libretificacaotjcore might be problematic. Click here for more details.

@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: libretificacaotjcore
3
+ Version: 0.1.0
4
+ Summary: Biblioteca para centralizar conexao com filas no rabbit e banco de dados no mongodb para os servicos de retificacao da TJ
5
+ Author-email: Jhonatan Azevedo <dev.azevedo@outlook.com>
6
+ Project-URL: Homepage, https://github.com/seu-usuario/libretificacaotjcore
7
+ Project-URL: Issues, https://github.com/seu-usuario/libretificacaotjcore/issues
8
+ Project-URL: Repository, https://github.com/seu-usuario/libretificacaotjcore
9
+ Keywords: tj,tributo justo,retificação,automação,pydantic,rabbitmq,boto3,motor
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Libraries
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Operating System :: OS Independent
22
+ Requires-Python: >=3.12
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: boto3>=1.39.16
25
+ Requires-Dist: motor>=3.7.1
26
+ Requires-Dist: pika>=1.3.2
27
+ Requires-Dist: pydantic>=2.11.7
File without changes
@@ -0,0 +1,31 @@
1
+ class ArquivoRepository:
2
+ def __init__(self, db):
3
+ self.__db = db
4
+
5
+ async def inserir_arquivo(self, arquivo: dict) -> bool:
6
+
7
+ try:
8
+ arquivo_no_db = await self.__db.arquivos.find_one(
9
+ {"SolicitacaoId": arquivo["solicitacaoId"], "cpf": arquivo["cpf"]}
10
+ )
11
+
12
+ if arquivo_no_db is None:
13
+ await self.__db.arquivos.insert_one(arquivo)
14
+ return True
15
+
16
+ await self.__db.arquivos.delete_one(
17
+ {"SolicitacaoId": arquivo["solicitacaoId"], "cpf": arquivo["cpf"]}
18
+ )
19
+ await self.__db.arquivos.insert_one(arquivo)
20
+ return True
21
+ except Exception as e:
22
+ print(f"❌ Erro ao inserir o arquivo: {e}")
23
+ return False
24
+
25
+ async def remover_arquivo(self, solicitacaoId: int) -> bool:
26
+ try:
27
+ await self.__db.arquivos.delete_many({"SolicitacaoId": solicitacaoId})
28
+ return True
29
+ except Exception as e:
30
+ print(f"❌ Erro ao remover o arquivo: {e}")
31
+ return False
@@ -0,0 +1,33 @@
1
+ import motor.motor_asyncio
2
+ from bson import ObjectId
3
+ from datetime import datetime
4
+
5
+ class ConfigDb:
6
+ def __init__(self, host: str, user: str, password: str, port: int, db_name: str):
7
+ self.host = host
8
+ self.user = user
9
+ self.password = password
10
+ self.port = port
11
+ self.db_name = db_name
12
+
13
+ self.client = motor.motor_asyncio.AsyncIOMotorClient(
14
+ f"mongodb://{self.host}:{self.port}"
15
+ )
16
+ self.db = self.client[self.db_name]
17
+ self.db_initialized = False
18
+
19
+
20
+ async def criar_schema(self):
21
+ global _db_initialized
22
+ if not self.db_initialized:
23
+ if "arquivos" not in (await self.db.list_collection_names()):
24
+ await self.db.create_collection("arquivos")
25
+
26
+ await self.db.arquivos.create_index([("cnpj", 1)])
27
+ await self.db.arquivos.create_index([("SolicitacaoId", 1)])
28
+ await self.db.arquivos.create_index([("id", 1)], unique=True)
29
+ self.db_initialized = True
30
+
31
+ async def get_db(self):
32
+ await self.criar_schema()
33
+ return self.db
@@ -0,0 +1,63 @@
1
+ from datetime import datetime, date, timedelta
2
+ import re
3
+ from pydantic import BaseModel, Field, field_validator
4
+
5
+
6
+ class SolicitacaoDTO(BaseModel):
7
+ solicitacaoId: int = Field(..., description="ID da solicitação")
8
+ cnpj: str = Field(..., description="CNPJ da empresa")
9
+ dataInicio: str = Field(..., description="Data de início no formato YYYY-MM-DD")
10
+ dataFim: str = Field(..., description="Data de fim no formato YYYY-MM-DD")
11
+ certificadoId: int = Field(..., description="ID do certificado")
12
+
13
+
14
+ # Validar e transformar solicitacaoId
15
+ @field_validator('solicitacaoId')
16
+ @classmethod
17
+ def validar_solicitacao_id(cls, v: int) -> int:
18
+ if v <= 0:
19
+ raise ValueError("O solicitacaoId deve ser um inteiro positivo.")
20
+ return v
21
+
22
+ # Validar e transformar certificadoId
23
+ @field_validator('certificadoId')
24
+ @classmethod
25
+ def validar_certificado_id(cls, v: int) -> int:
26
+ if v <= 0:
27
+ raise ValueError("O certificadoId deve ser um inteiro positivo.")
28
+ return v
29
+
30
+ # Validar CNPJ (apenas estrutura com 14 dígitos)
31
+ @field_validator('cnpj')
32
+ @classmethod
33
+ def validar_cnpj(cls, v: str) -> str:
34
+ cnpj_limpo = re.sub(r'\D', '', v)
35
+ if len(cnpj_limpo) != 14 or not cnpj_limpo.isdigit():
36
+ raise ValueError("O CNPJ deve conter 14 dígitos numéricos.")
37
+ return cnpj_limpo
38
+
39
+ # Validar e transformar dataInicio
40
+ @field_validator('dataInicio', mode='before')
41
+ @classmethod
42
+ def formatar_data_inicio(cls, value: str) -> date:
43
+ try:
44
+ return datetime.strptime(value, "%Y-%m-%d").date()
45
+ except ValueError:
46
+ raise ValueError("A dataInicio deve estar no formato YYYY-MM-DD.")
47
+
48
+ # Validar e transformar dataFim (último dia do mês)
49
+ @field_validator('dataFim', mode='before')
50
+ @classmethod
51
+ def ajustar_data_fim(cls, value: str) -> date:
52
+ try:
53
+ ano, mes = map(int, value.split("-")[:2])
54
+ if mes < 1 or mes > 12:
55
+ raise ValueError
56
+ if mes == 12:
57
+ proximo_mes = datetime(ano + 1, 1, 1)
58
+ else:
59
+ proximo_mes = datetime(ano, mes + 1, 1)
60
+ return (proximo_mes - timedelta(days=1)).date()
61
+ except Exception:
62
+ raise ValueError("A dataFim deve estar no formato YYYY-MM-DD e conter um mês válido.")
63
+
@@ -0,0 +1,54 @@
1
+ import pika
2
+ import json
3
+
4
+
5
+ class RabbitMQConsumer:
6
+ def __init__(
7
+ self,
8
+ host,
9
+ queue,
10
+ username,
11
+ password,
12
+ vhost="/",
13
+ ):
14
+ self.host = host
15
+ self.queue = queue
16
+ self.username = username
17
+ self.password = password
18
+ self.vhost = vhost
19
+ self.connection = None
20
+ self.channel = None
21
+
22
+ def connect(self):
23
+ credentials = pika.PlainCredentials(self.username, self.password)
24
+ parameters = pika.ConnectionParameters(
25
+ host=self.host,
26
+ credentials=credentials,
27
+ virtual_host=self.vhost,
28
+ heartbeat=60,
29
+ blocked_connection_timeout=300,
30
+ )
31
+
32
+ self.connection = pika.BlockingConnection(parameters)
33
+ self.channel = self.connection.channel()
34
+ self.channel.queue_declare(queue=self.queue, durable=True)
35
+
36
+ def start_consuming(self, callback):
37
+ def on_message(ch, method, properties, body):
38
+ mensagem = json.loads(body)
39
+ callback(mensagem)
40
+ ch.basic_ack(delivery_tag=method.delivery_tag)
41
+
42
+ if not self.channel:
43
+ raise RuntimeError("❌ Canal RabbitMQ não conectado. Chame connect() antes.")
44
+
45
+ self.channel.basic_qos(prefetch_count=1)
46
+ self.channel.basic_consume(queue=self.queue, on_message_callback=on_message)
47
+ print(
48
+ f'[*] Aguardando mensagens na fila "{self.queue}". Para sair pressione CTRL+C'
49
+ )
50
+ self.channel.start_consuming()
51
+
52
+ def close(self):
53
+ if self.connection:
54
+ self.connection.close()
@@ -0,0 +1,83 @@
1
+ import asyncio
2
+ from functools import partial
3
+ import os
4
+ import boto3
5
+ from botocore.exceptions import ClientError
6
+
7
+ class S3Service:
8
+ def __init__(self, aws_access_key_id, aws_secret_access_key, region_name, bucket_name, bucket_path):
9
+ self.s3 = boto3.client(
10
+ "s3",
11
+ aws_access_key_id=aws_access_key_id,
12
+ aws_secret_access_key=aws_secret_access_key,
13
+ region_name=region_name,
14
+ )
15
+
16
+ self.bucket_name = bucket_name
17
+ self.bucket_path = bucket_path
18
+
19
+ self.loop = asyncio.get_running_loop()
20
+
21
+ async def save_on_s3(self, file_path, file_name):
22
+ try:
23
+ await self.loop.run_in_executor(
24
+ None,
25
+ self.s3.upload_file,
26
+ file_path,
27
+ self.bucket_name,
28
+ self.bucket_path + file_name,
29
+ )
30
+ except Exception as e:
31
+ print(f"❌ Erro ao salvar o arquivo no S3: {e}")
32
+
33
+ async def save_many_paths_on_s3(self, file_paths):
34
+ """
35
+ Salva vários arquivos no S3 informando apenas os caminhos locais.
36
+ O nome do arquivo no S3 será o mesmo do arquivo local.
37
+ """
38
+ tasks = [
39
+ self.save_on_s3(
40
+ file_path["caminho_arquivo_local"], file_path["nome_arquivo"]
41
+ )
42
+ for file_path in file_paths
43
+ ]
44
+ await asyncio.gather(*tasks)
45
+
46
+ async def file_on_s3(self, file_name):
47
+ try:
48
+ head_object_func = partial(
49
+ self.s3.head_object,
50
+ Bucket=self.bucket_name,
51
+ Key=self.bucket_path + file_name,
52
+ )
53
+
54
+ await self.loop.run_in_executor(None, head_object_func)
55
+ return True
56
+ except ClientError as e:
57
+ if e.response["Error"]["Code"] == "404":
58
+ return False
59
+
60
+ raise
61
+ except Exception as e:
62
+ print(f"❌ Erro ao obter o arquivo do S3: {e}")
63
+ return False
64
+
65
+ async def get_file_from_s3(self, file_name, destination_path):
66
+ try:
67
+ os.makedirs(os.path.dirname(destination_path), exist_ok=True)
68
+
69
+ key = self.bucket_path + file_name
70
+ print(f"🔍 Verificando chave: {key}")
71
+ download_func = partial(
72
+ self.s3.download_file, self.bucket_name, key, destination_path
73
+ )
74
+
75
+ await self.loop.run_in_executor(None, download_func)
76
+ print(f"📖✅ Arquivo '{file_name}' baixado com sucesso.")
77
+ except ClientError as e:
78
+ if e.response["Error"]["Code"] == "404":
79
+ print(f"⚠️ Arquivo '{file_name}' não encontrado no S3.")
80
+ else:
81
+ print(f"❌ Erro ao baixar o arquivo do S3: {e}")
82
+ except Exception as e:
83
+ print(f"❌ Erro inesperado ao baixar o arquivo do S3: {e}")
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: libretificacaotjcore
3
+ Version: 0.1.0
4
+ Summary: Biblioteca para centralizar conexao com filas no rabbit e banco de dados no mongodb para os servicos de retificacao da TJ
5
+ Author-email: Jhonatan Azevedo <dev.azevedo@outlook.com>
6
+ Project-URL: Homepage, https://github.com/seu-usuario/libretificacaotjcore
7
+ Project-URL: Issues, https://github.com/seu-usuario/libretificacaotjcore/issues
8
+ Project-URL: Repository, https://github.com/seu-usuario/libretificacaotjcore
9
+ Keywords: tj,tributo justo,retificação,automação,pydantic,rabbitmq,boto3,motor
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Libraries
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Operating System :: OS Independent
22
+ Requires-Python: >=3.12
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: boto3>=1.39.16
25
+ Requires-Dist: motor>=3.7.1
26
+ Requires-Dist: pika>=1.3.2
27
+ Requires-Dist: pydantic>=2.11.7
@@ -0,0 +1,15 @@
1
+ README.md
2
+ pyproject.toml
3
+ libretificacaotjcore/__init__.py
4
+ libretificacaotjcore.egg-info/PKG-INFO
5
+ libretificacaotjcore.egg-info/SOURCES.txt
6
+ libretificacaotjcore.egg-info/dependency_links.txt
7
+ libretificacaotjcore.egg-info/requires.txt
8
+ libretificacaotjcore.egg-info/top_level.txt
9
+ libretificacaotjcore/database/__init__.py
10
+ libretificacaotjcore/database/arquivo_repository.py
11
+ libretificacaotjcore/database/config_db.py
12
+ libretificacaotjcore/dtos/solicitacao_dto.py
13
+ libretificacaotjcore/services/__init__.py
14
+ libretificacaotjcore/services/rabbitmq_consumer.py
15
+ libretificacaotjcore/services/s3_service.py
@@ -0,0 +1,4 @@
1
+ boto3>=1.39.16
2
+ motor>=3.7.1
3
+ pika>=1.3.2
4
+ pydantic>=2.11.7
@@ -0,0 +1 @@
1
+ libretificacaotjcore
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ build-backend = "setuptools.build_meta"
3
+ requires = ["setuptools>=61.0", "wheel"]
4
+
5
+ [project]
6
+ authors = [
7
+ {name = "Jhonatan Azevedo", email = "dev.azevedo@outlook.com"},
8
+ ]
9
+ description = "Biblioteca para centralizar conexao com filas no rabbit e banco de dados no mongodb para os servicos de retificacao da TJ"
10
+ keywords = ["tj", "tributo justo", "retificação", "automação", "pydantic", "rabbitmq", "boto3", "motor"]
11
+ name = "libretificacaotjcore"
12
+ readme = "README.md"
13
+ requires-python = ">=3.12"
14
+ version = "0.1.0"
15
+
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "Topic :: Software Development :: Libraries",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.8",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Operating System :: OS Independent",
29
+ ]
30
+
31
+ dependencies = [
32
+ "boto3>=1.39.16",
33
+ "motor>=3.7.1",
34
+ "pika>=1.3.2",
35
+ "pydantic>=2.11.7",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/seu-usuario/libretificacaotjcore"
40
+ Issues = "https://github.com/seu-usuario/libretificacaotjcore/issues"
41
+ Repository = "https://github.com/seu-usuario/libretificacaotjcore"
42
+
43
+ [tool.setuptools.packages.find]
44
+ include = ["libretificacaotjcore*"]
45
+ where = ["."]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+