csc-cia-stne 0.1.19__py3-none-any.whl → 0.1.21__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.
- csc_cia_stne/bc_sta.py +80 -72
- {csc_cia_stne-0.1.19.dist-info → csc_cia_stne-0.1.21.dist-info}/METADATA +1 -1
- {csc_cia_stne-0.1.19.dist-info → csc_cia_stne-0.1.21.dist-info}/RECORD +6 -6
- {csc_cia_stne-0.1.19.dist-info → csc_cia_stne-0.1.21.dist-info}/WHEEL +0 -0
- {csc_cia_stne-0.1.19.dist-info → csc_cia_stne-0.1.21.dist-info}/licenses/LICENCE +0 -0
- {csc_cia_stne-0.1.19.dist-info → csc_cia_stne-0.1.21.dist-info}/top_level.txt +0 -0
csc_cia_stne/bc_sta.py
CHANGED
@@ -6,7 +6,7 @@ import xml.etree.ElementTree as ET
|
|
6
6
|
from xml.dom.minidom import parseString
|
7
7
|
from pydantic import BaseModel, ValidationError, field_validator, Field, HttpUrl
|
8
8
|
from typing import Literal, Dict, Union, Optional, List
|
9
|
-
from datetime import datetime
|
9
|
+
from datetime import datetime, timedelta
|
10
10
|
|
11
11
|
log = logging.getLogger('__main__')
|
12
12
|
|
@@ -499,90 +499,99 @@ class BC_STA:
|
|
499
499
|
#return f"Failed to create protocol. Status code: {response.status_code}, Reason: {response.reason}"
|
500
500
|
return resposta
|
501
501
|
|
502
|
-
def listar_arquivos(self,
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
identificadorDocumento (Optional[str], optional): Identificador documento. Default=None (Todos).
|
511
|
-
qtd (int, optional): Quantidade de arquivos na resposta. Default=100 (máximo=100).
|
512
|
-
tipo_arquivo (list, optional): Tipo de arquivo para fazer download. Default=None (Todos). Opções: ['ACCS002', 'ACCS003', 'AJUD301', 'AJUD302', 'AJUD303', 'AJUD304', 'AJUD305', 'AJUD308', 'AJUD309', 'AJUD310', 'AJUD331', 'AMES102', 'AMTF102', 'ASVR9810', 'ATXB001'].
|
513
|
-
|
514
|
-
Returns:
|
515
|
-
list: Lista de arquivos do STA
|
516
|
-
"""
|
502
|
+
def listar_arquivos(self,
|
503
|
+
nivel: Literal['RES', 'BAS', 'COMPL'],
|
504
|
+
inicio: str,
|
505
|
+
fim: str = None,
|
506
|
+
situacao: Optional[Literal['REC', 'A_REC']] = None,
|
507
|
+
identificadorDocumento: Optional[str] = None,
|
508
|
+
qtd: int = 100,
|
509
|
+
tipo_arquivo: list = None):
|
517
510
|
resultados = []
|
518
|
-
ultima_data = inicio
|
519
511
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
512
|
+
try:
|
513
|
+
# Parse seguro para datetime (assume formato ISO 'AAAA-MM-DDTHH:MM:SS')
|
514
|
+
dt_inicio = datetime.fromisoformat(inicio)
|
515
|
+
dt_fim = datetime.fromisoformat(fim) if fim else None
|
516
|
+
ultima_dt = dt_inicio
|
517
|
+
|
518
|
+
while True:
|
519
|
+
# Se já passamos do fim, encerra antes de chamar a API
|
520
|
+
if dt_fim and ultima_dt >= dt_fim:
|
521
|
+
break
|
522
|
+
|
523
|
+
# Monta a URL usando a data atual do cursor
|
524
|
+
_inicio_str = ultima_dt.strftime("%Y-%m-%dT%H:%M:%S")
|
525
|
+
url = f"{self.base_url}/arquivos?tipoConsulta=AVANC&nivelDetalhe={nivel}"
|
526
|
+
url += f"&dataHoraInicio={_inicio_str}"
|
527
|
+
if situacao:
|
528
|
+
url += f"&situacaoTransmissao={situacao}"
|
529
|
+
if identificadorDocumento:
|
530
|
+
url += f"&identificadorDocumento={identificadorDocumento}"
|
531
|
+
if dt_fim:
|
532
|
+
_fim_str = dt_fim.strftime("%Y-%m-%dT%H:%M:%S")
|
533
|
+
url += f"&dataHoraFim={_fim_str}"
|
534
|
+
url += f"&qtdMaxResultados={qtd}"
|
535
|
+
|
536
|
+
response = requests.get(
|
537
|
+
url, headers=self.headers, auth=self.auth, timeout=60,
|
538
|
+
)
|
539
|
+
|
540
|
+
if response.status_code != 200:
|
541
|
+
log.error(f"Erro ao listar arquivos: response code {response.status_code}\n{response.text}")
|
542
|
+
return False
|
535
543
|
|
536
|
-
if response.status_code == 200:
|
537
|
-
|
538
544
|
try:
|
539
|
-
|
540
545
|
dados = xml_response_to_json(response.text)
|
546
|
+
if not dados:
|
547
|
+
break # sem mais resultados
|
541
548
|
|
542
|
-
|
543
|
-
|
544
|
-
break # Sai do loop se não houver mais dados
|
545
|
-
|
546
|
-
# Filtra apenas os arquivos do tipo 'AJUD308'
|
547
|
-
if tipo_arquivo is not None:
|
548
|
-
|
549
|
-
if isinstance(dados, list):
|
550
|
-
dados_filtrados = [arquivo for arquivo in dados if arquivo.get("TipoArquivo") in tipo_arquivo]
|
551
|
-
elif dados.get("TipoArquivo") in tipo_arquivo:
|
552
|
-
dados_filtrados = [dados]
|
553
|
-
|
554
|
-
resultados.extend(dados_filtrados)
|
555
|
-
|
556
|
-
else:
|
557
|
-
|
558
|
-
resultados.extend(dados)
|
549
|
+
# Normaliza dados para lista
|
550
|
+
itens = dados if isinstance(dados, list) else [dados]
|
559
551
|
|
560
|
-
#
|
561
|
-
if
|
552
|
+
# (opcional) filtra por tipo_arquivo
|
553
|
+
if tipo_arquivo is not None:
|
554
|
+
itens = [a for a in itens if a.get("TipoArquivo") in tipo_arquivo]
|
555
|
+
|
556
|
+
resultados.extend(itens)
|
557
|
+
|
558
|
+
# Atualiza o cursor a partir do último item retornado
|
559
|
+
# Busca o último com DataHoraDisponibilizacao
|
560
|
+
ultimo = None
|
561
|
+
for cand in reversed(itens):
|
562
|
+
if "DataHoraDisponibilizacao" in cand and cand["DataHoraDisponibilizacao"]:
|
563
|
+
ultimo = cand["DataHoraDisponibilizacao"]
|
564
|
+
break
|
565
|
+
|
566
|
+
if not ultimo:
|
567
|
+
# fallback: se o JSON bruto vier como dict/list diferente, tente no original
|
568
|
+
if isinstance(dados, list) and dados and "DataHoraDisponibilizacao" in dados[-1]:
|
569
|
+
ultimo = dados[-1]["DataHoraDisponibilizacao"]
|
570
|
+
elif isinstance(dados, dict) and "DataHoraDisponibilizacao" in dados:
|
571
|
+
ultimo = dados["DataHoraDisponibilizacao"]
|
572
|
+
|
573
|
+
if not ultimo:
|
574
|
+
log.error("Campo 'DataHoraDisponibilizacao' não encontrado ou estrutura inesperada.")
|
575
|
+
return False
|
562
576
|
|
563
|
-
|
577
|
+
# Cursor: último + 1s para evitar repetir o mesmo registro
|
578
|
+
proxima_dt = datetime.fromisoformat(ultimo) + timedelta(seconds=1)
|
564
579
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
else:
|
580
|
+
# Se a próxima dt já ultrapassa o fim, encerramos sem nova chamada
|
581
|
+
if dt_fim and proxima_dt > dt_fim:
|
582
|
+
break
|
570
583
|
|
571
|
-
|
572
|
-
return False
|
584
|
+
ultima_dt = proxima_dt
|
573
585
|
|
574
586
|
except ET.ParseError as e:
|
575
|
-
|
576
587
|
log.error(f"Erro ao processar XML: {e}")
|
577
588
|
return False
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
return resultados
|
585
|
-
|
589
|
+
|
590
|
+
return resultados
|
591
|
+
except Exception as e:
|
592
|
+
log.error(f"Erro em BC_STA:listar_arquivos: {e}")
|
593
|
+
return False
|
594
|
+
|
586
595
|
def download_arquivo(self,protocolo:str,filename:str=None):
|
587
596
|
"""Faz o download de um arquivo de um protocolo especifico
|
588
597
|
|
@@ -631,7 +640,6 @@ class BC_STA:
|
|
631
640
|
|
632
641
|
return {"success": False, "status_code": int(response.status_code), "content": response.text}
|
633
642
|
|
634
|
-
|
635
643
|
def qs_gerar_xml_string_responder_nao_cliente(self,protocolo_inicial_ordem:str,numctrlccs:str,cnpj_cpf:str,numctrlenvio:str,numprocjud:str,identdemissor:str,identddestinatario:str,domsist:str,nuop:str,dtmovto:datetime,cnpjbaseentrespons:str):
|
636
644
|
|
637
645
|
"""Gera a string do arquivo XML de resposta para nao-cliente para ser enviado ao STA
|
@@ -1,6 +1,6 @@
|
|
1
1
|
csc_cia_stne/__init__.py,sha256=jwLhGpOwFCow_6cqzwLn31WcIrMzutMZtEQpLL4bQtM,2638
|
2
2
|
csc_cia_stne/bc_correios.py,sha256=s2XjJ0iokMlcUv0mAy9saU3pc_G-6X8wltb_lFHIL6o,24717
|
3
|
-
csc_cia_stne/bc_sta.py,sha256=
|
3
|
+
csc_cia_stne/bc_sta.py,sha256=U3Z9LZ7-_LZXDx5DAuvIHwHIkwGpBLSt9VJfonWcJTk,28990
|
4
4
|
csc_cia_stne/email.py,sha256=y4xyPAe6_Mga5Wf6qAsDzYgn0f-zf2KshfItlWe58z8,8481
|
5
5
|
csc_cia_stne/ftp.py,sha256=eNkOUEXdw-9NYfuZjNo6Oh7EduD54g8N0cfD0LuOiTU,11516
|
6
6
|
csc_cia_stne/gcp_bigquery.py,sha256=foq8azvvv_f7uikMDslX9RcUIrx7RAS-Sn0AGW0QFQc,7231
|
@@ -38,8 +38,8 @@ csc_cia_stne/utilitarios/web_screen/__init__.py,sha256=5QcOPXKd95SvP2DoZiHS0gaU6
|
|
38
38
|
csc_cia_stne/utilitarios/web_screen/web_screen_abstract.py,sha256=PjL8Vgfj_JdKidia7RFyCkro3avYLQu4RZRos41sh3w,3241
|
39
39
|
csc_cia_stne/utilitarios/web_screen/web_screen_botcity.py,sha256=Xi5YJjl2pcxlX3OimqcBWRNXZEpAE7asyUjDJ4Oho5U,12297
|
40
40
|
csc_cia_stne/utilitarios/web_screen/web_screen_selenium.py,sha256=JLIcPJE9ZX3Pd6zG6oTRMqqUAY063UzLY3ReRlxmiSM,15581
|
41
|
-
csc_cia_stne-0.1.
|
42
|
-
csc_cia_stne-0.1.
|
43
|
-
csc_cia_stne-0.1.
|
44
|
-
csc_cia_stne-0.1.
|
45
|
-
csc_cia_stne-0.1.
|
41
|
+
csc_cia_stne-0.1.21.dist-info/licenses/LICENCE,sha256=LPGMtgKki2C3KEZP7hDhA1HBrlq5JCHkIeStUCLEMx4,1073
|
42
|
+
csc_cia_stne-0.1.21.dist-info/METADATA,sha256=obIzLQ4Cf6gGibFVcQgW1OlTuIcSsg7_d4Hw-s2s0a0,1464
|
43
|
+
csc_cia_stne-0.1.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
44
|
+
csc_cia_stne-0.1.21.dist-info/top_level.txt,sha256=ldo7GVv3tQx5KJvwBzdZzzQmjPys2NDVVn1rv0BOF2Q,13
|
45
|
+
csc_cia_stne-0.1.21.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|