libretificacaotjcore 0.1.37__tar.gz → 0.1.73__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.

Files changed (36) hide show
  1. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/PKG-INFO +2 -2
  2. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/database/arquivo_repository.py +10 -1
  3. libretificacaotjcore-0.1.73/libretificacaotjcore/database/config_db.py +82 -0
  4. libretificacaotjcore-0.1.73/libretificacaotjcore/database/depentente_invalido_1210_repository.py +34 -0
  5. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/database/protocolo_repository.py +3 -1
  6. libretificacaotjcore-0.1.73/libretificacaotjcore/database/rubrica_repository.py +35 -0
  7. libretificacaotjcore-0.1.73/libretificacaotjcore/database/solicitacao_xml_repository.py +40 -0
  8. libretificacaotjcore-0.1.73/libretificacaotjcore/database/tempo_processo_repository.py +119 -0
  9. libretificacaotjcore-0.1.73/libretificacaotjcore/dtos/processo_dto.py +79 -0
  10. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/dtos/solicitacao_dto.py +2 -1
  11. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/enums/e_eventos.py +1 -0
  12. libretificacaotjcore-0.1.73/libretificacaotjcore/enums/e_fase_retificacao.py +38 -0
  13. libretificacaotjcore-0.1.73/libretificacaotjcore/services/rabbitmq_consumer.py +61 -0
  14. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/services/request_servico_api.py +4 -3
  15. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore.egg-info/PKG-INFO +2 -2
  16. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore.egg-info/SOURCES.txt +5 -0
  17. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/pyproject.toml +2 -2
  18. libretificacaotjcore-0.1.37/libretificacaotjcore/database/config_db.py +0 -41
  19. libretificacaotjcore-0.1.37/libretificacaotjcore/enums/e_fase_retificacao.py +0 -31
  20. libretificacaotjcore-0.1.37/libretificacaotjcore/services/rabbitmq_consumer.py +0 -56
  21. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/README.md +0 -0
  22. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/__init__.py +0 -0
  23. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/database/__init__.py +0 -0
  24. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/database/certificado_repository.py +0 -0
  25. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/dtos/__init__.py +0 -0
  26. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/dtos/arquivo_dto.py +0 -0
  27. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/enums/__init__.py +0 -0
  28. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/services/__init__.py +0 -0
  29. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/services/crypto_pass_service.py +0 -0
  30. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/services/file_service.py +0 -0
  31. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/services/rabbitmq_publisher.py +0 -0
  32. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore/services/s3_service.py +0 -0
  33. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore.egg-info/dependency_links.txt +0 -0
  34. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore.egg-info/requires.txt +0 -0
  35. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/libretificacaotjcore.egg-info/top_level.txt +0 -0
  36. {libretificacaotjcore-0.1.37 → libretificacaotjcore-0.1.73}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: libretificacaotjcore
3
- Version: 0.1.37
3
+ Version: 0.1.73
4
4
  Summary: Biblioteca para centralizar conexao com filas no rabbit e banco de dados no mongodb para os servicos de retificacao da TJ
5
5
  Author-email: Jhonatan Azevedo <dev.azevedo@outlook.com>
6
6
  Project-URL: Homepage, https://github.com/seu-usuario/libretificacaotjcore
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3.13
21
21
  Classifier: Operating System :: OS Independent
22
- Requires-Python: >=3.12
22
+ Requires-Python: >=3.11
23
23
  Description-Content-Type: text/markdown
24
24
  Requires-Dist: aio-pika>=9.5.7
25
25
  Requires-Dist: aiofiles>=24.1.0
@@ -1,3 +1,5 @@
1
+
2
+ import uuid
1
3
  from pymongo.errors import BulkWriteError
2
4
 
3
5
  class ArquivoRepository:
@@ -5,12 +7,15 @@ class ArquivoRepository:
5
7
  self.__db = db
6
8
 
7
9
  async def inserir_arquivo(self, arquivo: dict) -> bool:
8
-
9
10
  try:
10
11
  arquivo_no_db = await self.__db.arquivos.find_one(
11
12
  {"solicitacaoId": arquivo["solicitacaoId"], "cpf": arquivo["cpf"]}
12
13
  )
13
14
 
15
+ # Gerar ID único se não existir
16
+ if 'id' not in arquivo or arquivo['id'] is None:
17
+ arquivo['id'] = str(uuid.uuid4())
18
+
14
19
  if arquivo_no_db is None:
15
20
  await self.__db.arquivos.insert_one(arquivo)
16
21
  return True
@@ -29,6 +34,10 @@ class ArquivoRepository:
29
34
  if not arquivos:
30
35
  return False
31
36
 
37
+ for arquivo in arquivos:
38
+ arquivo['id'] = str(uuid.uuid4())
39
+
40
+ # Agora usar apenas solicitacaoId e cpf para deletar
32
41
  filtros = [{"solicitacaoId": a["solicitacaoId"], "cpf": a["cpf"]} for a in arquivos]
33
42
  await self.__db.arquivos.delete_many({"$or": filtros})
34
43
 
@@ -0,0 +1,82 @@
1
+ import motor.motor_asyncio
2
+ import certifi
3
+
4
+ class ConfigDb:
5
+ def __init__(self, host: str, user: str, password: str, port: int, db_name: str):
6
+ self.host = host
7
+ self.user = user
8
+ self.password = password
9
+ self.port = port
10
+ self.db_name = db_name
11
+
12
+ auth = f"{self.user}:{self.password}@" if self.user and self.password else ""
13
+ # self.client = motor.motor_asyncio.AsyncIOMotorClient(
14
+ # f"mongodb+srv://{auth}{self.host}",
15
+ # tls=True,
16
+ # tlsCAFile=certifi.where(),
17
+ # tlsAllowInvalidCertificates=False,
18
+ # serverSelectionTimeoutMS=30000,
19
+ # socketTimeoutMS=20000,
20
+ # connectTimeoutMS=20000,
21
+ # retryWrites=True,
22
+ # w='majority'
23
+ # )
24
+
25
+ self.client = motor.motor_asyncio.AsyncIOMotorClient(
26
+ f"mongodb://{auth}{self.host}:{self.port}/"
27
+ )
28
+ self.__db = self.client[self.db_name]
29
+ self.db_initialized = False
30
+
31
+
32
+ async def criar_schema(self):
33
+ global _db_initialized
34
+ if not self.db_initialized:
35
+ if "arquivos" not in (await self.__db.list_collection_names()):
36
+ await self.__db.create_collection("arquivos")
37
+
38
+ await self.__db.arquivos.create_index([("cnpj", 1)])
39
+ await self.__db.arquivos.create_index([("solicitacaoId", 1)])
40
+ await self.__db.arquivos.create_index([("id", 1)], unique=True)
41
+ await self.__db.arquivos.create_index([("solicitacaoId", 1), ("cpf", 1)], unique=True)
42
+ self.db_initialized = True
43
+
44
+ if "protocolos" not in (await self.__db.list_collection_names()):
45
+ await self.__db.create_collection("protocolos")
46
+
47
+ await self.__db.protocolos.create_index([("cnpj", 1)])
48
+ await self.__db.protocolos.create_index([("solicitacaoId", 1)])
49
+ await self.__db.protocolos.create_index([("id", 1)], unique=True)
50
+ await self.__db.protocolos.create_index([("solicitacaoId", 1), ("evento", 1)], unique=True)
51
+ self.db_initialized = True
52
+
53
+ if "rubricas" not in (await self.__db.list_collection_names()):
54
+ await self.__db.create_collection("rubricas")
55
+
56
+ await self.__db.rubricas.create_index([("cnpj", 1)])
57
+ await self.__db.rubricas.create_index([("solicitacaoId", 1)], unique=True)
58
+ await self.__db.rubricas.create_index([("id", 1)], unique=True)
59
+ self.db_initialized = True
60
+
61
+ if "tempo_processos" not in (await self.__db.list_collection_names()):
62
+ await self.__db.create_collection("tempo_processos")
63
+
64
+ await self.__db.tempo_processos.create_index([("SolicitacaoId", 1)])
65
+ await self.__db.tempo_processos.create_index([("id", 1)], unique=True)
66
+ self.db_initialized = True
67
+
68
+ if "solicitacao_xmls" not in (await self.__db.list_collection_names()):
69
+ await self.__db.create_collection("solicitacao_xmls")
70
+
71
+ await self.__db.solicitacao_xmls.create_index([("solicitacaoId", 1)], unique=True)
72
+ self.db_initialized = True
73
+
74
+ if "dependente_invalido_1210" not in (await self.__db.list_collection_names()):
75
+ await self.__db.create_collection("dependente_invalido_1210")
76
+
77
+ await self.__db.dependente_invalido_1210.create_index([("solicitacaoId", 1)])
78
+ self.db_initialized = True
79
+
80
+ async def get_db(self):
81
+ await self.criar_schema()
82
+ return self.__db
@@ -0,0 +1,34 @@
1
+ import uuid
2
+
3
+ class DepententeInvalido1210Repository:
4
+ def __init__(self, db):
5
+ self.__db = db
6
+
7
+ async def inserir(self, depentente_invalido: dict) -> bool:
8
+
9
+ try:
10
+ dep_ja_cadastrado = await self.__db.dependente_invalido_1210.find_one({"solicitacaoId": depentente_invalido["solicitacaoId"], "cpf": depentente_invalido["cpf"], "cpf_dep": depentente_invalido["cpf_dep"], "per_apur": depentente_invalido["per_apur"]})
11
+ if dep_ja_cadastrado:
12
+ print(f"⚠️ Dependente inválido 1210 já cadastrado: {dep_ja_cadastrado}")
13
+ return False
14
+
15
+ await self.__db.dependente_invalido_1210.insert_one(depentente_invalido)
16
+ return True
17
+ except Exception as e:
18
+ print(f"❌ Erro ao inserir o dependente inválido 1210: {e}")
19
+ return False
20
+
21
+ async def buscar_por_solicitacao_id(self, solicitacaoId: int) -> list:
22
+ try:
23
+ return await self.__db.dependente_invalido_1210.find({"solicitacaoId": solicitacaoId}).to_list(length=None)
24
+ except Exception as e:
25
+ print(f"❌ Erro ao buscar dependente inválido 1210 por solicitacaoId: {e}")
26
+ return []
27
+
28
+ async def remover(self, solicitacaoId: int, cpf_colaborador: str) -> bool:
29
+ try:
30
+ await self.__db.dependente_invalido_1210.delete_many({"solicitacaoId": solicitacaoId, "cpf": cpf_colaborador})
31
+ return True
32
+ except Exception as e:
33
+ print(f"❌ Erro ao remover dependente inválido 1210: {e}")
34
+ return False
@@ -1,3 +1,4 @@
1
+ import uuid
1
2
  from pymongo.errors import BulkWriteError
2
3
 
3
4
  class ProtocoloRepository:
@@ -11,6 +12,7 @@ class ProtocoloRepository:
11
12
  {"solicitacaoId": protocolo["solicitacaoId"], "evento": protocolo["evento"]}
12
13
  )
13
14
 
15
+ protocolo['id'] = str(uuid.uuid4())
14
16
  if protocolo_no_db is None:
15
17
  await self.__db.protocolos.insert_one(protocolo)
16
18
  return True
@@ -29,7 +31,7 @@ class ProtocoloRepository:
29
31
  if not protocolos:
30
32
  return False
31
33
 
32
- filtros = [{"solicitacaoId": a["solicitacaoId"], "evento": a["evento"]} for a in protocolos]
34
+ filtros = [{"solicitacaoId": a["solicitacaoId"], "evento": a["evento"], a['id']: str(uuid.uuid4())} for a in protocolos]
33
35
  await self.__db.protocolos.delete_many({"$or": filtros})
34
36
 
35
37
  await self.__db.protocolos.insert_many(protocolos)
@@ -0,0 +1,35 @@
1
+ import uuid
2
+ from pymongo.errors import BulkWriteError
3
+
4
+ class RubricaRepository:
5
+ def __init__(self, db):
6
+ self.__db = db
7
+
8
+ async def inserir_rubrica(self, rubrica: dict) -> bool:
9
+
10
+ try:
11
+ rubricas_no_db = await self.__db.rubricas.find_one(
12
+ {"solicitacaoId": rubrica["solicitacaoId"]}
13
+ )
14
+
15
+ rubrica['id'] = str(uuid.uuid4())
16
+
17
+ if rubricas_no_db is None:
18
+ await self.__db.rubricas.insert_one(rubrica)
19
+ return True
20
+
21
+ await self.__db.rubricas.delete_one(
22
+ {"solicitacaoId": rubrica["solicitacaoId"]}
23
+ )
24
+ await self.__db.rubricas.insert_one(rubrica)
25
+ return True
26
+ except Exception as e:
27
+ print(f"❌ Erro ao inserir o rubrica: {e}")
28
+ return False
29
+
30
+ async def buscar_por_solicitacao_id(self, solicitacaoId: int) -> dict:
31
+ try:
32
+ return await self.__db.rubricas.find_one({"solicitacaoId": solicitacaoId})
33
+ except Exception as e:
34
+ print(f"❌ Erro ao buscar rubricas por solicitacaoId: {e}")
35
+ return {}
@@ -0,0 +1,40 @@
1
+ import uuid
2
+
3
+ class SolicitacaoXmlsRepository:
4
+ def __init__(self, db):
5
+ self.__db = db
6
+
7
+ async def inserir_solicitacao_xml(self, solicitacao_xml: dict) -> bool:
8
+
9
+ try:
10
+ solicitacao_xml_no_db = await self.__db.solicitacao_xmls.find_one(
11
+ {"solicitacaoId": solicitacao_xml["solicitacaoId"]}
12
+ )
13
+
14
+ if solicitacao_xml_no_db is None:
15
+ await self.__db.solicitacao_xmls.insert_one(solicitacao_xml)
16
+ return True
17
+
18
+ await self.__db.solicitacao_xmls.delete_one(
19
+ {"solicitacaoId": solicitacao_xml["solicitacaoId"]}
20
+ )
21
+ await self.__db.solicitacao_xmls.insert_one(solicitacao_xml)
22
+ return True
23
+ except Exception as e:
24
+ print(f"❌ Erro ao inserir o solicitacao xml: {e}")
25
+ return False
26
+
27
+ async def buscar_por_solicitacao_id(self, solicitacaoId: int) -> dict:
28
+ try:
29
+ return await self.__db.solicitacao_xmls.find_one({"solicitacaoId": solicitacaoId})
30
+ except Exception as e:
31
+ print(f"❌ Erro ao buscar solicitacao xml por solicitacaoId: {e}")
32
+ return {}
33
+
34
+ async def remover_por_solicitacao_id(self, solicitacaoId: int) -> bool:
35
+ try:
36
+ await self.__db.solicitacao_xmls.delete_one({"solicitacaoId": solicitacaoId})
37
+ return True
38
+ except Exception as e:
39
+ print(f"❌ Erro ao remover solicitacao xml por solicitacaoId: {e}")
40
+ return False
@@ -0,0 +1,119 @@
1
+ from datetime import datetime
2
+ import uuid
3
+ from pymongo.errors import BulkWriteError
4
+
5
+ from libretificacaotjcore.dtos.processo_dto import ProcessoDto
6
+ from libretificacaotjcore.enums.e_fase_retificacao import EFaseRetificacao
7
+
8
+ class TempoProcessoRepository:
9
+ def __init__(self, db):
10
+ self.__db = db
11
+
12
+ async def inserir_processo(self, *, processo: ProcessoDto) -> bool:
13
+ try:
14
+ processo_dict = processo.model_dump(exclude_none=True)
15
+ processo_dict["DataInicio"] = processo.DataInicio.strftime("%Y-%m-%d")
16
+ processo_dict["DataFim"] = processo.DataFim.strftime("%Y-%m-%d")
17
+ processo_dict["FaseDescricao"] = EFaseRetificacao(processo.Fase).name
18
+
19
+ processo_no_db = await self.__db.tempo_processos.find_one(
20
+ {
21
+ "SolicitacaoId": processo.SolicitacaoId,
22
+ "Fase": processo.Fase,
23
+ "DataInicio": processo_dict["DataInicio"],
24
+ "DataFim": processo_dict["DataFim"],
25
+ }
26
+ )
27
+
28
+ processo_dict["id"] = str(uuid.uuid4())
29
+
30
+ if processo_no_db is None:
31
+ processo_dict["InicioProcesso"] = datetime.now()
32
+ await self.__db.tempo_processos.insert_one(processo_dict)
33
+ return True
34
+
35
+ await self.__db.tempo_processos.delete_one(
36
+ {
37
+ "SolicitacaoId": processo.SolicitacaoId,
38
+ "Fase": processo.Fase,
39
+ "DataInicio": processo_dict["DataInicio"],
40
+ "DataFim": processo_dict["DataFim"],
41
+ }
42
+ )
43
+
44
+ processo_dict["InicioProcesso"] = datetime.now()
45
+ await self.__db.tempo_processos.insert_one(processo_dict)
46
+ return True
47
+
48
+ except Exception as e:
49
+ print(f"❌ Erro ao inserir o processo: {e}")
50
+ return False
51
+
52
+ async def atualizar_processo(self, *, processo: ProcessoDto) -> bool:
53
+ try:
54
+ processo_dict = processo.model_dump()
55
+ processo_dict["DataInicio"] = processo.DataInicio.strftime("%Y-%m-%d")
56
+ processo_dict["DataFim"] = processo.DataFim.strftime("%Y-%m-%d")
57
+
58
+ processo_no_db = await self.__db.tempo_processos.find_one(
59
+ {
60
+ "SolicitacaoId": processo.SolicitacaoId,
61
+ "Fase": processo.Fase,
62
+ "DataInicio": processo_dict["DataInicio"],
63
+ "DataFim": processo_dict["DataFim"],
64
+ }
65
+ )
66
+
67
+ if processo_no_db is None:
68
+ return False
69
+
70
+ processo_no_db['FimProcesso'] = datetime.now()
71
+ tempo_de_processo = self._tempo_de_processo(processo_no_db['InicioProcesso'], processo_no_db['FimProcesso'])
72
+ processo_no_db['TempoDeProcesso'] = tempo_de_processo
73
+
74
+ await self.__db.tempo_processos.update_one(
75
+ {
76
+ "SolicitacaoId": processo.SolicitacaoId,
77
+ "Fase": processo.Fase,
78
+ "DataInicio": processo_dict["DataInicio"],
79
+ "DataFim": processo_dict["DataFim"],
80
+ },
81
+ {"$set": processo_no_db
82
+ })
83
+ return True
84
+ except Exception as e:
85
+ print(f"❌ Erro ao atualizar o processo: {e}")
86
+ return False
87
+
88
+ async def buscar_por_solicitacao_id(self, solicitacao_id: int) -> list[ProcessoDto]:
89
+ try:
90
+ processos = await self.__db.tempo_processos.find(
91
+ {
92
+ "SolicitacaoId": solicitacao_id
93
+ }
94
+ ).to_list(length=None)
95
+ processos_dto = []
96
+
97
+ for processo in processos:
98
+ processo_dto = ProcessoDto(**processo)
99
+ processos_dto.append(processo_dto)
100
+
101
+ return processos_dto
102
+ except Exception as e:
103
+ print(f"❌ Erro ao buscar os processos por solicitação: {e}")
104
+ return []
105
+
106
+ def _tempo_de_processo(self, tempo_inicio: datetime, tempo_fim: datetime) -> str | None:
107
+ if tempo_inicio and tempo_fim:
108
+ delta = tempo_fim - tempo_inicio
109
+ total_segundos = int(delta.total_seconds())
110
+
111
+ horas = total_segundos // 3600
112
+ minutos = (total_segundos % 3600) // 60
113
+ segundos = total_segundos % 60
114
+
115
+ tempo_formatado = f"{horas:02d}:{minutos:02d}:{segundos:02d}"
116
+ tempo_formatado = "00:00:01" if tempo_formatado == "00:00:00" else tempo_formatado
117
+ return tempo_formatado
118
+
119
+ return None
@@ -0,0 +1,79 @@
1
+ from datetime import date, datetime, timedelta
2
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
3
+ from libretificacaotjcore.enums.e_fase_retificacao import EFaseRetificacao
4
+
5
+
6
+ class ProcessoDto(BaseModel):
7
+ model_config = ConfigDict(frozen=False)
8
+ SolicitacaoId: int = Field(..., description="ID da solicitação")
9
+ DataInicio: date = Field(..., description="Data de início no formato YYYY-MM-DD")
10
+ DataFim: date = Field(..., description="Data de fim no formato YYYY-MM-DD")
11
+ Fase: int | None = Field(None, description="Fase de retificação")
12
+ InicioProcesso: datetime | None = Field(None, description="Data e hora de início do processo")
13
+ FimProcesso: datetime | None = Field(None, description="Data e hora de fim do processo")
14
+ TempoDeProcesso: str | None = Field(None, description="Tempo de processamento")
15
+ Observacoes: str | None = Field(None, description="Observações adicionais")
16
+
17
+ # --- Validadores ---
18
+
19
+ @field_validator("SolicitacaoId")
20
+ @classmethod
21
+ def validar_solicitacao_id(cls, v: int) -> int:
22
+ if v <= 0:
23
+ raise ValueError("O solicitacaoId deve ser um inteiro positivo.")
24
+ return v
25
+
26
+ @field_validator("DataInicio", mode="before")
27
+ @classmethod
28
+ def formatar_data_inicio(cls, value) -> date:
29
+ """
30
+ Aceita date, datetime ou string.
31
+ """
32
+ if isinstance(value, date):
33
+ return value
34
+ if isinstance(value, datetime):
35
+ return value.date()
36
+ if isinstance(value, str):
37
+ try:
38
+ return datetime.strptime(value, "%Y-%m-%d").date()
39
+ except ValueError as ve:
40
+ raise ValueError("A DataInicio deve estar no formato YYYY-MM-DD.") from ve
41
+ raise TypeError("Tipo inválido para DataInicio.")
42
+
43
+ @field_validator("DataFim", mode="before")
44
+ @classmethod
45
+ def ajustar_data_fim(cls, value) -> date:
46
+ """
47
+ Aceita date, datetime ou string.
48
+ Retorna o último dia do mês da data fornecida.
49
+ """
50
+ if isinstance(value, datetime):
51
+ value = value.date()
52
+ if isinstance(value, date):
53
+ ano, mes = value.year, value.month
54
+ elif isinstance(value, str):
55
+ try:
56
+ ano, mes = map(int, value.split("-")[:2])
57
+ except Exception:
58
+ raise ValueError("A DataFim deve estar no formato YYYY-MM-DD.")
59
+ else:
60
+ raise TypeError("Tipo inválido para DataFim.")
61
+
62
+ if mes < 1 or mes > 12:
63
+ raise ValueError("A DataFim deve conter um mês válido (1–12).")
64
+
65
+ # calcula o último dia do mês
66
+ if mes == 12:
67
+ proximo_mes = datetime(ano + 1, 1, 1)
68
+ else:
69
+ proximo_mes = datetime(ano, mes + 1, 1)
70
+ return (proximo_mes - timedelta(days=1)).date()
71
+
72
+ @field_validator("Fase")
73
+ @classmethod
74
+ def validar_fase(cls, v):
75
+ if v is None:
76
+ return v
77
+ if v not in EFaseRetificacao:
78
+ raise ValueError(f"Fase '{v}' não é válida.")
79
+ return v
@@ -11,7 +11,8 @@ class SolicitacaoDTO(BaseModel):
11
11
  DataInicio: date = Field(..., description="Data de início no formato YYYY-MM-DD")
12
12
  DataFim: date = Field(..., description="Data de fim no formato YYYY-MM-DD")
13
13
  CertificadoId: int = Field(..., description="ID do certificado")
14
- Fase: int | None = Field(None, description="fase de retificação")
14
+ Fase: int | None = Field(None, description="Fase de retificação")
15
+ FaseUnica: bool = Field(False, description="Fase única")
15
16
 
16
17
  @field_validator("SolicitacaoId")
17
18
  @classmethod
@@ -2,6 +2,7 @@ from enum import Enum
2
2
 
3
3
 
4
4
  class EEventos(str, Enum):
5
+ S1010 = "S-1010"
5
6
  S1200 = "S-1200"
6
7
  S1210 = "S-1210"
7
8
  S1298 = "S-1298"
@@ -0,0 +1,38 @@
1
+ from enum import Enum
2
+
3
+
4
+ class EFaseRetificacao(Enum):
5
+ NaoIniciado = 0
6
+ SolicitacaoXml = 1
7
+ AguardandoXml = 2
8
+ DownloadXml = 3
9
+ ExtraindoDadosDoXml = 4
10
+ #? Abertura de Competencia
11
+ EstruturandoXmlAberturaCompetencia = 5
12
+ AberturaDeCompetencia = 6
13
+ ConsultandoESocialAberturaCompetencia = 7
14
+ #? Rubricas
15
+ EstruturandoXmlInclusaoRubricas = 8
16
+ InclusaoDasRubricas = 9
17
+ ConsultandoESocialInclusaoRubricas = 10
18
+ #? Exclusao de Pagamentos
19
+ EstruturandoXmlExclusaoPagamentos = 11
20
+ ExclusaoDePagamentos = 12
21
+ ConsultandoESocialExclusaoPagamentos = 13
22
+ #? Retificacao
23
+ EstruturandoXmlRetificacaoRemuneracao = 14
24
+ RetificacaoDaRemuneracao = 15
25
+ ConsultandoESocialRetificacaoRemuneracao = 16
26
+ #? Desligamento
27
+ EstruturandoXmlDesligamento = 17
28
+ Desligamento = 18
29
+ ConsultandoESocialDesligamento = 19
30
+ #? Inclusao de Pagamentos
31
+ EstruturandoXmlInclusaoPagamentos = 20
32
+ InclusaoDosPagamentos = 21
33
+ ConsultandoESocialInclusaoPagamentos = 22
34
+ #? Fechamento de Competencia
35
+ EstruturandoXmlFechamentoCompetencia = 23
36
+ FechamentoDeCompetencia = 24
37
+ ConsultandoESocialFechamentoCompetencia = 25
38
+ Finalizado = 26
@@ -0,0 +1,61 @@
1
+ import asyncio
2
+ import aio_pika
3
+ import json
4
+
5
+ class RabbitMQConsumer:
6
+ def __init__(
7
+ self,
8
+ *,
9
+ host: str,
10
+ queue: str,
11
+ username: str,
12
+ password: str,
13
+ vhost: str = "/",
14
+ prefetch_count: int = 1
15
+ ):
16
+ self.host = host
17
+ self.queue = queue
18
+ self.username = username
19
+ self.password = password
20
+ self.vhost = vhost
21
+ self.connection = None
22
+ self.channel = None
23
+ self.prefetch_count = prefetch_count
24
+
25
+ async def connect(self):
26
+ self.connection = await aio_pika.connect_robust(
27
+ host=self.host,
28
+ login=self.username,
29
+ password=self.password,
30
+ virtualhost=self.vhost,
31
+ heartbeat=600,
32
+ )
33
+ self.channel = await self.connection.channel()
34
+ await self.channel.set_qos(prefetch_count=self.prefetch_count)
35
+ await self.channel.declare_queue(self.queue, durable=True)
36
+
37
+ async def start_consuming(self, callback):
38
+ if not self.channel:
39
+ raise RuntimeError("❌ Canal RabbitMQ não conectado. Chame connect() antes.")
40
+
41
+ queue = await self.channel.get_queue(self.queue)
42
+
43
+ async def on_message(message):
44
+ async with message.process():
45
+ try:
46
+ mensagem = json.loads(message.body.decode())
47
+ await callback(mensagem) # aqui sim passa o DTO
48
+ except Exception as e:
49
+ print(f"❌ Erro ao processar mensagem: {e}")
50
+
51
+ await queue.consume(on_message) # registra callback
52
+
53
+ print(f'[*] Aguardando mensagens na fila "{self.queue}". Para sair pressione CTRL+C')
54
+
55
+ # Mantém o consumer rodando
56
+ await asyncio.Future()
57
+
58
+
59
+ async def close(self):
60
+ if self.connection:
61
+ await self.connection.close()
@@ -5,13 +5,14 @@ class RequestServicoApi:
5
5
  def __init__(self, url, token):
6
6
  self.url = url
7
7
  self.token = token
8
- self.client = httpx.AsyncClient(timeout=120, verify=False)
8
+ self.client = httpx.AsyncClient(timeout=1200, verify=False)
9
+ self.status_code_success = [200, 201, 204]
9
10
 
10
- async def handler(self, *, mensagem_atualizacao: dict):
11
+ async def handler(self, *, mensagem_atualizacao: dict | list):
11
12
  print(self.token)
12
13
  response = await self.client.post(self.url, json=mensagem_atualizacao)
13
14
 
14
- if response.status_code != 200:
15
+ if response.status_code not in self.status_code_success:
15
16
  raise Exception(f"Erro ao fazer request ao servico de API: {response.status_code}")
16
17
 
17
18
  await self.close()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: libretificacaotjcore
3
- Version: 0.1.37
3
+ Version: 0.1.73
4
4
  Summary: Biblioteca para centralizar conexao com filas no rabbit e banco de dados no mongodb para os servicos de retificacao da TJ
5
5
  Author-email: Jhonatan Azevedo <dev.azevedo@outlook.com>
6
6
  Project-URL: Homepage, https://github.com/seu-usuario/libretificacaotjcore
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3.13
21
21
  Classifier: Operating System :: OS Independent
22
- Requires-Python: >=3.12
22
+ Requires-Python: >=3.11
23
23
  Description-Content-Type: text/markdown
24
24
  Requires-Dist: aio-pika>=9.5.7
25
25
  Requires-Dist: aiofiles>=24.1.0
@@ -10,9 +10,14 @@ libretificacaotjcore/database/__init__.py
10
10
  libretificacaotjcore/database/arquivo_repository.py
11
11
  libretificacaotjcore/database/certificado_repository.py
12
12
  libretificacaotjcore/database/config_db.py
13
+ libretificacaotjcore/database/depentente_invalido_1210_repository.py
13
14
  libretificacaotjcore/database/protocolo_repository.py
15
+ libretificacaotjcore/database/rubrica_repository.py
16
+ libretificacaotjcore/database/solicitacao_xml_repository.py
17
+ libretificacaotjcore/database/tempo_processo_repository.py
14
18
  libretificacaotjcore/dtos/__init__.py
15
19
  libretificacaotjcore/dtos/arquivo_dto.py
20
+ libretificacaotjcore/dtos/processo_dto.py
16
21
  libretificacaotjcore/dtos/solicitacao_dto.py
17
22
  libretificacaotjcore/enums/__init__.py
18
23
  libretificacaotjcore/enums/e_eventos.py
@@ -17,8 +17,8 @@ keywords = [
17
17
  ]
18
18
  name = "libretificacaotjcore"
19
19
  readme = "README.md"
20
- requires-python = ">=3.12"
21
- version = "0.1.37"
20
+ requires-python = ">=3.11"
21
+ version = "0.1.73"
22
22
 
23
23
  classifiers = [
24
24
  "Development Status :: 3 - Alpha",
@@ -1,41 +0,0 @@
1
- import motor.motor_asyncio
2
-
3
- class ConfigDb:
4
- def __init__(self, host: str, user: str, password: str, port: int, db_name: str):
5
- self.host = host
6
- self.user = user
7
- self.password = password
8
- self.port = port
9
- self.db_name = db_name
10
-
11
- self.client = motor.motor_asyncio.AsyncIOMotorClient(
12
- f"mongodb://{self.host}:{self.port}"
13
- )
14
- self.__db = self.client[self.db_name]
15
- self.db_initialized = False
16
-
17
-
18
- async def criar_schema(self):
19
- global _db_initialized
20
- if not self.db_initialized:
21
- if "arquivos" not in (await self.__db.list_collection_names()):
22
- await self.__db.create_collection("arquivos")
23
-
24
- await self.__db.arquivos.create_index([("cnpj", 1)])
25
- await self.__db.arquivos.create_index([("solicitacaoId", 1)])
26
- await self.__db.arquivos.create_index([("id", 1)], unique=True)
27
- await self.__db.arquivos.create_index([("solicitacaoId", 1), ("cpf", 1)], unique=True)
28
- self.db_initialized = True
29
-
30
- if "protocolos" not in (await self.__db.list_collection_names()):
31
- await self.__db.create_collection("protocolos")
32
-
33
- await self.__db.protocolos.create_index([("cnpj", 1)])
34
- await self.__db.protocolos.create_index([("solicitacaoId", 1)])
35
- await self.__db.protocolos.create_index([("id", 1)], unique=True)
36
- await self.__db.protocolos.create_index([("solicitacaoId", 1), ("evento", 1)], unique=True)
37
- self.db_initialized = True
38
-
39
- async def get_db(self):
40
- await self.criar_schema()
41
- return self.__db
@@ -1,31 +0,0 @@
1
- from enum import Enum
2
-
3
-
4
- class EFaseRetificacao(Enum):
5
- NaoIniciado = 0
6
- SolicitacaoXml = 1
7
- AguardandoXml = 2
8
- DownloadXml = 3
9
- ExtraindoDadosDoXml = 4
10
- AguardandoRubrica = 5
11
- EstruturandoXmlAberturaCompetencia = 6
12
- EstruturandoXmlExclusaoPagamentos = 7
13
- EstruturandoXmlRetificacaoRemuneracao = 8
14
- EstruturandoXmlInclusaoPagamentos = 9
15
- EstruturandoXmlDesligamento = 10
16
- EstruturandoXmlFechamentoCompetencia = 11
17
- AberturaDeCompetencia = 12
18
- ConsultandoESocialAberturaCompetencia = 13
19
- InclusaoDasRubricas = 14
20
- ConsultandoESocialInclusaoRubricas = 15
21
- ExclusaoDePagamentos = 16
22
- ConsultandoESocialExclusaoPagamentos = 17
23
- RetificacaoDaRemuneracao = 18
24
- ConsultandoESocialRetificacaoRemuneracao = 19
25
- InclusaoDosPagamentos = 20
26
- ConsultandoESocialInclusaoPagamentos = 21
27
- Desligamento = 22
28
- ConsultandoESocialDesligamento = 23
29
- FechamentoDeCompetencia = 24
30
- ConsultandoESocialFechamentoCompetencia = 25
31
- Finalizado = 26
@@ -1,56 +0,0 @@
1
- import pika
2
- import json
3
-
4
-
5
- class RabbitMQConsumer:
6
- def __init__(
7
- self,
8
- host: str,
9
- queue: str,
10
- username: str,
11
- password: str,
12
- vhost: str ="/",
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
- self.connect()
22
-
23
- def connect(self):
24
- credentials = pika.PlainCredentials(self.username, self.password)
25
- parameters = pika.ConnectionParameters(
26
- host=self.host,
27
- credentials=credentials,
28
- virtual_host=self.vhost,
29
- heartbeat=600,
30
- blocked_connection_timeout=1200,
31
- )
32
-
33
- self.connection = pika.BlockingConnection(parameters)
34
- self.channel = self.connection.channel()
35
- self.channel.queue_declare(queue=self.queue, durable=True)
36
-
37
- def start_consuming(self, callback):
38
- def on_message(ch, method, properties, body):
39
- mensagem = json.loads(body)
40
- callback(mensagem)
41
- ch.basic_ack(delivery_tag=method.delivery_tag)
42
- self.close()
43
-
44
- if not self.channel:
45
- raise RuntimeError("❌ Canal RabbitMQ não conectado. Chame connect() antes.")
46
-
47
- self.channel.basic_qos(prefetch_count=1)
48
- self.channel.basic_consume(queue=self.queue, on_message_callback=on_message)
49
- print(
50
- f'[*] Aguardando mensagens na fila "{self.queue}". Para sair pressione CTRL+C'
51
- )
52
- self.channel.start_consuming()
53
-
54
- def close(self):
55
- if self.connection:
56
- self.connection.close()