teste
This commit is contained in:
parent
e568673a14
commit
45858dc952
259
Pedidos_mar.py
259
Pedidos_mar.py
@ -460,10 +460,92 @@ BASE_HEADERS = {
|
||||
# 4) LOOP POR LOJA
|
||||
# ===============================
|
||||
|
||||
def process_stores(stores_to_process, all_data, base_headers, token, is_retry=False):
|
||||
def save_store_data_to_db(store_data, stats):
|
||||
"""
|
||||
Processa uma lista de lojas e retorna os dados coletados e as lojas que falharam.
|
||||
Se is_retry=True, remove dados existentes da loja antes de adicionar novos (evita duplicação).
|
||||
Salva os dados de uma loja no banco de dados imediatamente.
|
||||
Deleta os pedidos existentes e insere os novos.
|
||||
Retorna True se salvou com sucesso, False caso contrário.
|
||||
"""
|
||||
if not store_data:
|
||||
return True # Nada para salvar, considera sucesso
|
||||
|
||||
try:
|
||||
conn = pyodbc.connect(DB_CONNECTION_STRING)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Obter lista única de pedidos para deletar
|
||||
unique_orders = list(set([record["Pedido"] for record in store_data]))
|
||||
stats["pedidos_unicos"] += len(unique_orders)
|
||||
|
||||
# Deletar registros existentes dos pedidos
|
||||
if unique_orders:
|
||||
placeholders = ','.join(['?' for _ in unique_orders])
|
||||
delete_query = f"DELETE FROM [GINSENG].[dbo].[extrato_pedidos_mar] WHERE [Pedido] IN ({placeholders})"
|
||||
cursor.execute(delete_query, unique_orders)
|
||||
stats["registros_deletados"] += cursor.rowcount
|
||||
conn.commit()
|
||||
|
||||
# Query de inserção
|
||||
insert_query = """
|
||||
INSERT INTO [GINSENG].[dbo].[extrato_pedidos_mar]
|
||||
([Loja], [Pedido], [Data], [Tipo], [Status], [Valor], [PDV], [Observacao],
|
||||
[SellBOT], [SellEUD], [SellQDB], [Itens], [SKUs], [ValorTotal], [PercentualAtendido],
|
||||
[ItemBU], [SKU], [DescricaoItem], [StatusItem], [PrecoUnitario],
|
||||
[QtdSolicitada], [QtdAceita], [QtdAtendida], [QtdFaturada], [PercentualItem],
|
||||
[NFNumero], [NFDataMAR], [DataEntrega], [CodigoAtendimento], [MotivoRecusa])
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
"""
|
||||
|
||||
# Inserir dados
|
||||
for record in store_data:
|
||||
cursor.execute(insert_query,
|
||||
record["Loja"],
|
||||
record["Pedido"],
|
||||
to_date(record["Data"]),
|
||||
record["Tipo"],
|
||||
record["Status"],
|
||||
to_decimal(record["Valor (R$)"]),
|
||||
record["PDV"] if record["PDV"] else None,
|
||||
record["Observação"] if record["Observação"] else None,
|
||||
record["Sell BOT"] if record["Sell BOT"] else None,
|
||||
record["Sell EUD"] if record["Sell EUD"] else None,
|
||||
record["Sell QDB"] if record["Sell QDB"] else None,
|
||||
to_int(record["Itens"]),
|
||||
str(record["SKUs"]) if record["SKUs"] else None,
|
||||
to_decimal(record["Valor Total"]),
|
||||
record["% Atendido"] if record["% Atendido"] else None,
|
||||
record["Item BU"] if record["Item BU"] else None,
|
||||
record["SKU"] if record["SKU"] else None,
|
||||
record["Descrição Item"] if record["Descrição Item"] else None,
|
||||
record["Status Item"] if record["Status Item"] else None,
|
||||
to_decimal(record["Preço Unit."]),
|
||||
to_int(record["Qtd Solicitada"]),
|
||||
to_int(record["Qtd Aceita"]),
|
||||
to_int(record["Qtd Atendida"]),
|
||||
to_int(record["Qtd Faturada"]),
|
||||
to_int(record["% Item"]),
|
||||
record["NF Número"] if record["NF Número"] else None,
|
||||
to_date(record["NF Data MAR"]),
|
||||
to_date(record["Data Entrega"]),
|
||||
record["Código Atendimento"] if record["Código Atendimento"] else None,
|
||||
record["Motivo Recusa"] if record["Motivo Recusa"] else None
|
||||
)
|
||||
stats["registros_inseridos"] += 1
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f" [ERRO BD] Erro ao salvar no banco: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def process_stores(stores_to_process, base_headers, token, stats):
|
||||
"""
|
||||
Processa uma lista de lojas e salva no banco imediatamente após cada loja.
|
||||
Retorna as lojas que falharam e o token atualizado.
|
||||
"""
|
||||
failed = []
|
||||
processed_count = 0
|
||||
@ -500,28 +582,23 @@ def process_stores(stores_to_process, all_data, base_headers, token, is_retry=Fa
|
||||
base_headers["authorization"] = token
|
||||
base_headers["x-authorization"] = token
|
||||
|
||||
# Se é retry e a loja foi processada com sucesso, remove dados antigos dessa loja
|
||||
# para evitar duplicação (caso tenha coletado dados parciais antes de falhar)
|
||||
if is_retry and len(store_data) > 0:
|
||||
old_count = len(all_data)
|
||||
all_data[:] = [record for record in all_data if record["Loja"] != store]
|
||||
removed = old_count - len(all_data)
|
||||
if removed > 0:
|
||||
print(f" [RETRY] Removidos {removed} registros antigos da loja {store} para evitar duplicação")
|
||||
|
||||
# Adicionar dados da loja ao total
|
||||
all_data.extend(store_data)
|
||||
processed_count += 1
|
||||
|
||||
if len(store_data) == 0:
|
||||
failed.append(store)
|
||||
|
||||
print(f"Loja {store} processada: {len(store_data)} registros")
|
||||
print(f"Loja {store}: 0 registros (falha)")
|
||||
else:
|
||||
# Salvar no banco imediatamente
|
||||
print(f" Salvando {len(store_data)} registros no banco...")
|
||||
if save_store_data_to_db(store_data, stats):
|
||||
print(f" ✓ Loja {store}: {len(store_data)} registros salvos")
|
||||
stats["lojas_salvas"] += 1
|
||||
else:
|
||||
failed.append(store)
|
||||
print(f" ✗ Loja {store}: erro ao salvar no banco")
|
||||
|
||||
return failed, token
|
||||
|
||||
all_data = []
|
||||
failed_stores = []
|
||||
|
||||
# Estatísticas para relatório final
|
||||
stats = {
|
||||
@ -530,14 +607,16 @@ stats = {
|
||||
"lojas_falha_inicial": [],
|
||||
"lojas_recuperadas_retry": [],
|
||||
"lojas_falha_final": [],
|
||||
"lojas_salvas": 0,
|
||||
"registros_inseridos": 0,
|
||||
"registros_deletados": 0,
|
||||
"duplicatas_removidas": 0,
|
||||
"pedidos_unicos": 0
|
||||
}
|
||||
|
||||
failed_stores = []
|
||||
|
||||
# Primeira passagem: processar todas as lojas
|
||||
failed_stores, TOKEN = process_stores(STORES, all_data, BASE_HEADERS, TOKEN)
|
||||
failed_stores, TOKEN = process_stores(STORES, BASE_HEADERS, TOKEN, stats)
|
||||
|
||||
# Guardar lojas que falharam na primeira tentativa
|
||||
stats["lojas_falha_inicial"] = failed_stores.copy()
|
||||
@ -564,9 +643,9 @@ while failed_stores and retry_round < FAILED_STORES_MAX_RETRIES:
|
||||
# Guardar lojas antes do retry para comparar depois
|
||||
lojas_antes_retry = set(failed_stores)
|
||||
|
||||
# Tentar processar as lojas que falharam (is_retry=True para evitar duplicação)
|
||||
# Tentar processar as lojas que falharam
|
||||
stores_to_retry = failed_stores.copy()
|
||||
failed_stores, TOKEN = process_stores(stores_to_retry, all_data, BASE_HEADERS, TOKEN, is_retry=True)
|
||||
failed_stores, TOKEN = process_stores(stores_to_retry, BASE_HEADERS, TOKEN, stats)
|
||||
|
||||
# Identificar lojas que foram recuperadas neste retry
|
||||
lojas_recuperadas = lojas_antes_retry - set(failed_stores)
|
||||
@ -585,141 +664,6 @@ if failed_stores:
|
||||
print(f" {', '.join(failed_stores)}")
|
||||
print(f"{'=' * 60}")
|
||||
|
||||
# ===============================
|
||||
# 5) SALVAR NO BANCO DE DADOS
|
||||
# ===============================
|
||||
|
||||
if all_data:
|
||||
# Remover duplicatas em all_data antes de inserir
|
||||
# Usa uma chave composta: Loja + Pedido + SKU
|
||||
print(f"\nVerificando duplicatas em all_data...")
|
||||
seen = set()
|
||||
unique_data = []
|
||||
duplicates_removed = 0
|
||||
|
||||
for record in all_data:
|
||||
# Criar chave única baseada nos campos que identificam um registro
|
||||
key = (
|
||||
record.get("Loja", ""),
|
||||
record.get("Pedido", ""),
|
||||
record.get("SKU", "")
|
||||
)
|
||||
if key not in seen:
|
||||
seen.add(key)
|
||||
unique_data.append(record)
|
||||
else:
|
||||
duplicates_removed += 1
|
||||
|
||||
if duplicates_removed > 0:
|
||||
print(f"[AVISO] Removidas {duplicates_removed} linhas duplicadas de all_data")
|
||||
all_data = unique_data
|
||||
|
||||
stats["duplicatas_removidas"] = duplicates_removed
|
||||
print(f"Total de registros após deduplicação: {len(all_data)}")
|
||||
|
||||
print(f"\nConectando ao banco de dados...")
|
||||
|
||||
try:
|
||||
# Conectar ao banco de dados
|
||||
conn = pyodbc.connect(DB_CONNECTION_STRING)
|
||||
cursor = conn.cursor()
|
||||
|
||||
print(f"Conexão estabelecida com sucesso!")
|
||||
|
||||
# Obter lista única de pedidos para deletar
|
||||
unique_orders = list(set([record["Pedido"] for record in all_data]))
|
||||
stats["pedidos_unicos"] = len(unique_orders)
|
||||
print(f"Total de pedidos únicos a processar: {len(unique_orders)}")
|
||||
|
||||
# Deletar registros existentes em lotes de 500
|
||||
print(f"Deletando registros existentes dos pedidos...")
|
||||
batch_size = 500
|
||||
deleted_count = 0
|
||||
|
||||
for i in range(0, len(unique_orders), batch_size):
|
||||
batch = unique_orders[i:i + batch_size]
|
||||
placeholders = ','.join(['?' for _ in batch])
|
||||
delete_query = f"DELETE FROM [GINSENG].[dbo].[extrato_pedidos_mar] WHERE [Pedido] IN ({placeholders})"
|
||||
|
||||
cursor.execute(delete_query, batch)
|
||||
deleted_count += cursor.rowcount
|
||||
conn.commit()
|
||||
print(f" Deletados {deleted_count} registros (lote {i//batch_size + 1}/{(len(unique_orders)-1)//batch_size + 1})...")
|
||||
|
||||
stats["registros_deletados"] = deleted_count
|
||||
print(f"Total de registros deletados: {deleted_count}")
|
||||
|
||||
# Query de inserção
|
||||
print(f"\nInserindo {len(all_data)} novos registros...")
|
||||
insert_query = """
|
||||
INSERT INTO [GINSENG].[dbo].[extrato_pedidos_mar]
|
||||
([Loja], [Pedido], [Data], [Tipo], [Status], [Valor], [PDV], [Observacao],
|
||||
[SellBOT], [SellEUD], [SellQDB], [Itens], [SKUs], [ValorTotal], [PercentualAtendido],
|
||||
[ItemBU], [SKU], [DescricaoItem], [StatusItem], [PrecoUnitario],
|
||||
[QtdSolicitada], [QtdAceita], [QtdAtendida], [QtdFaturada], [PercentualItem],
|
||||
[NFNumero], [NFDataMAR], [DataEntrega], [CodigoAtendimento], [MotivoRecusa])
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
"""
|
||||
|
||||
# Inserir dados em lote
|
||||
records_inserted = 0
|
||||
for record in all_data:
|
||||
cursor.execute(insert_query,
|
||||
record["Loja"], # varchar
|
||||
record["Pedido"], # varchar
|
||||
to_date(record["Data"]), # date
|
||||
record["Tipo"], # varchar
|
||||
record["Status"], # nvarchar
|
||||
to_decimal(record["Valor (R$)"]), # decimal
|
||||
record["PDV"] if record["PDV"] else None, # varchar
|
||||
record["Observação"] if record["Observação"] else None, # varchar
|
||||
record["Sell BOT"] if record["Sell BOT"] else None, # varchar
|
||||
record["Sell EUD"] if record["Sell EUD"] else None, # varchar
|
||||
record["Sell QDB"] if record["Sell QDB"] else None, # varchar
|
||||
to_int(record["Itens"]), # int
|
||||
str(record["SKUs"]) if record["SKUs"] else None, # varchar (não int!)
|
||||
to_decimal(record["Valor Total"]), # decimal
|
||||
record["% Atendido"] if record["% Atendido"] else None, # varchar
|
||||
record["Item BU"] if record["Item BU"] else None, # varchar
|
||||
record["SKU"] if record["SKU"] else None, # varchar
|
||||
record["Descrição Item"] if record["Descrição Item"] else None, # nvarchar
|
||||
record["Status Item"] if record["Status Item"] else None, # varchar
|
||||
to_decimal(record["Preço Unit."]), # decimal
|
||||
to_int(record["Qtd Solicitada"]), # int
|
||||
to_int(record["Qtd Aceita"]), # int
|
||||
to_int(record["Qtd Atendida"]), # int
|
||||
to_int(record["Qtd Faturada"]), # int
|
||||
to_int(record["% Item"]), # int
|
||||
record["NF Número"] if record["NF Número"] else None, # varchar
|
||||
to_date(record["NF Data MAR"]), # date
|
||||
to_date(record["Data Entrega"]), # date
|
||||
record["Código Atendimento"] if record["Código Atendimento"] else None, # varchar
|
||||
record["Motivo Recusa"] if record["Motivo Recusa"] else None # varchar
|
||||
)
|
||||
records_inserted += 1
|
||||
|
||||
# Commit a cada 100 registros para melhor performance
|
||||
if records_inserted % 100 == 0:
|
||||
conn.commit()
|
||||
print(f" {records_inserted}/{len(all_data)} registros inseridos...")
|
||||
|
||||
# Commit final
|
||||
conn.commit()
|
||||
|
||||
stats["registros_inseridos"] = records_inserted
|
||||
print(f"\n✓ Dados salvos com sucesso no banco de dados!")
|
||||
print(f"Total de registros inseridos: {records_inserted}")
|
||||
|
||||
# Fechar conexão
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ Erro ao salvar no banco de dados: {e}")
|
||||
|
||||
else:
|
||||
print("\nNenhum dado encontrado para salvar.")
|
||||
|
||||
# ===============================
|
||||
# 6) RELATÓRIO FINAL
|
||||
# ===============================
|
||||
@ -748,7 +692,6 @@ if stats['lojas_falha_final']:
|
||||
|
||||
print("\n📦 ESTATÍSTICAS DE DADOS:")
|
||||
print(f" Pedidos únicos processados: {stats['pedidos_unicos']}")
|
||||
print(f" Duplicatas removidas (memória): {stats['duplicatas_removidas']}")
|
||||
print(f" Registros deletados do banco: {stats['registros_deletados']}")
|
||||
print(f" Registros inseridos no banco: {stats['registros_inseridos']}")
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user