From c7c3b95f0b3994885be347d6a966fc7c763b6cb1 Mon Sep 17 00:00:00 2001 From: andersonid Date: Fri, 4 Apr 2025 09:24:45 -0300 Subject: [PATCH] =?UTF-8?q?refactor:=20melhora=20processo=20de=20seed=20de?= =?UTF-8?q?=20dados=20com=20melhor=20tratamento=20de=20erros=20e=20concorr?= =?UTF-8?q?=C3=AAncia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seed.py | 32 ++++++++ seed_data.py | 220 +++++++++++++++++++++++++++------------------------ 2 files changed, 148 insertions(+), 104 deletions(-) create mode 100644 seed.py diff --git a/seed.py b/seed.py new file mode 100644 index 0000000..6e2390f --- /dev/null +++ b/seed.py @@ -0,0 +1,32 @@ +from seed_data import seed_database +from functions.database import Base, engine, get_db_connection +import time +import os + +def wait_for_db(): + db_path = os.path.expanduser("~/.local/share/controles/database.db") + max_attempts = 30 + attempt = 0 + + while attempt < max_attempts: + if os.path.exists(db_path): + try: + db = get_db_connection() + db.execute("SELECT 1") + return True + except: + pass + print(f"Aguardando banco de dados... tentativa {attempt + 1}/{max_attempts}") + time.sleep(1) + attempt += 1 + + return False + +if __name__ == "__main__": + print("Aguardando banco de dados estar pronto...") + if wait_for_db(): + print("Iniciando população do banco de dados...") + seed_database() + print("Banco de dados populado com sucesso!") + else: + print("Erro: Banco de dados não ficou pronto a tempo.") \ No newline at end of file diff --git a/seed_data.py b/seed_data.py index 1aadaa8..7a3262c 100644 --- a/seed_data.py +++ b/seed_data.py @@ -2,16 +2,16 @@ from datetime import datetime, timedelta from functions.database import ( Base, Militante, CotaMensal, TipoPagamento, Pagamento, MaterialVendido, TipoMaterial, VendaJornalAvulso, AssinaturaAnual, - RelatorioCotasMensais, RelatorioVendasMateriais, engine, get_db_connection, + RelatorioCotasMensais, RelatorioVendasMateriais, engine, SessionLocal, Setor, ComiteCentral, Usuario, Role, EmailMilitante, Endereco ) import random from faker import Faker +import time fake = Faker('pt_BR') -db_session = get_db_connection() -def criar_tipos_pagamento(): +def criar_tipos_pagamento(session): """Cria tipos de pagamento padrão""" tipos = [ "Dinheiro", @@ -21,11 +21,11 @@ def criar_tipos_pagamento(): "Transferência Bancária" ] for tipo in tipos: - if not db_session.query(TipoPagamento).filter_by(descricao=tipo).first(): - db_session.add(TipoPagamento(descricao=tipo)) - db_session.commit() + if not session.query(TipoPagamento).filter_by(descricao=tipo).first(): + session.add(TipoPagamento(descricao=tipo)) + session.commit() -def criar_tipos_material(): +def criar_tipos_material(session): """Cria tipos de material padrão""" tipos = [ "Jornal", @@ -35,98 +35,111 @@ def criar_tipos_material(): "Cartilha" ] for tipo in tipos: - if not db_session.query(TipoMaterial).filter_by(descricao=tipo).first(): - db_session.add(TipoMaterial(descricao=tipo)) - db_session.commit() + if not session.query(TipoMaterial).filter_by(descricao=tipo).first(): + session.add(TipoMaterial(descricao=tipo)) + session.commit() -def criar_militantes(num_militantes): +def criar_militantes(session, num_militantes): print(f"\nCriando {num_militantes} militantes...") militantes = [] - emails_usados = set() # Conjunto para rastrear emails já usados + emails_usados = set() + + # Obter um setor existente + setor = session.query(Setor).first() + if not setor: + print("Erro: Nenhum setor encontrado!") + return [] for i in range(num_militantes): - nome = fake.name() - cpf = fake.cpf() - - # Gerar email único - while True: - email = fake.email() - if email not in emails_usados: - emails_usados.add(email) - break - - # Criar endereço - endereco = Endereco( - estado=fake.estado_sigla(), - cidade=fake.city(), - bairro=fake.bairro(), - rua=fake.street_name(), - numero=str(random.randint(1, 999)), - complemento=f"Bloco {random.randint(1, 10)}, Apto {random.randint(1, 999)}" if random.random() < 0.3 else None, - cep=fake.postcode() - ) - db_session.add(endereco) - db_session.flush() # Para obter o ID do endereço - - print(f"Criando militante {i+1}: {nome} (CPF: {cpf})") - - # Criar militante - militante = Militante( - nome=nome, - cpf=cpf, - titulo_eleitoral=str(random.randint(100000000000, 999999999999)), - data_nascimento=fake.date_of_birth(minimum_age=18, maximum_age=65), - data_entrada_oci=fake.date_between(start_date='-5y', end_date='today'), - data_efetivacao_oci=fake.date_between(start_date='-4y', end_date='today'), - telefone1=fake.phone_number(), - telefone2=fake.phone_number() if random.random() < 0.3 else None, - profissao=fake.job(), - regime_trabalho=random.choice(['CLT', 'PJ', 'Estatutário', 'Autônomo']), - empresa=fake.company(), - contratante=fake.company() if random.random() < 0.2 else None, - instituicao_ensino=fake.company() if random.random() < 0.4 else None, - tipo_instituicao=random.choice(['Federal', 'Estadual', 'Municipal', 'Privada']) if random.random() < 0.4 else None, - sindicato=fake.company() if random.random() < 0.6 else None, - cargo_sindical=random.choice(['Diretor', 'Delegado', 'Conselheiro']) if random.random() < 0.3 else None, - dirigente_sindical=random.random() < 0.2, - central_sindical=random.choice(['CUT', 'CSP-Conlutas', 'CTB', 'Força Sindical']) if random.random() < 0.4 else None, - endereco_id=endereco.id, - responsabilidades=random.randint(0, 1023) # Valor aleatório para responsabilidades - ) - db_session.add(militante) - db_session.flush() # Para obter o ID do militante - - # Criar email do militante - email_militante = EmailMilitante( - militante_id=militante.id, - endereco_email=email - ) - db_session.add(email_militante) - - militantes.append(militante) + try: + nome = fake.name() + cpf = fake.cpf() + + while True: + email = fake.email() + if email not in emails_usados: + emails_usados.add(email) + break + + endereco = Endereco( + estado=fake.estado_sigla(), + cidade=fake.city(), + bairro=fake.bairro(), + rua=fake.street_name(), + numero=str(random.randint(1, 999)), + complemento=f"Bloco {random.randint(1, 10)}, Apto {random.randint(1, 999)}" if random.random() < 0.3 else None, + cep=fake.postcode() + ) + session.add(endereco) + session.flush() + + print(f"Criando militante {i+1}: {nome} (CPF: {cpf})") + + militante = Militante( + nome=nome, + cpf=cpf, + titulo_eleitoral=str(random.randint(100000000000, 999999999999)), + data_nascimento=fake.date_of_birth(minimum_age=18, maximum_age=65), + data_entrada_oci=fake.date_between(start_date='-5y', end_date='today'), + data_efetivacao_oci=fake.date_between(start_date='-4y', end_date='today'), + telefone1=fake.phone_number(), + telefone2=fake.phone_number() if random.random() < 0.3 else None, + profissao=fake.job(), + regime_trabalho=random.choice(['CLT', 'PJ', 'Estatutário', 'Autônomo']), + empresa=fake.company(), + contratante=fake.company() if random.random() < 0.2 else None, + instituicao_ensino=fake.company() if random.random() < 0.4 else None, + tipo_instituicao=random.choice(['Federal', 'Estadual', 'Municipal', 'Privada']) if random.random() < 0.4 else None, + sindicato=fake.company() if random.random() < 0.6 else None, + cargo_sindical=random.choice(['Diretor', 'Delegado', 'Conselheiro']) if random.random() < 0.3 else None, + dirigente_sindical=random.random() < 0.2, + central_sindical=random.choice(['CUT', 'CSP-Conlutas', 'CTB', 'Força Sindical']) if random.random() < 0.4 else None, + endereco_id=endereco.id, + responsabilidades=random.randint(0, 1023) + ) + session.add(militante) + session.flush() + + email_militante = EmailMilitante( + militante_id=militante.id, + endereco_email=email + ) + session.add(email_militante) + + militantes.append(militante) + + # Commit a cada militante para evitar transações muito longas + session.commit() + + except Exception as e: + print(f"Erro ao criar militante {i+1}: {e}") + session.rollback() + continue - db_session.commit() return militantes -def criar_cotas(militantes, quantidade_por_militante=3): - """Cria cotas mensais fictícias""" +def criar_cotas(session, militantes, quantidade_por_militante=3): print(f"Criando {quantidade_por_militante} cotas para cada um dos {len(militantes)} militantes...") for militante in militantes: - print(f"Criando cotas para militante {militante.nome}") - for i in range(quantidade_por_militante): - data_base = datetime.now() - timedelta(days=30 * i) - valor = random.uniform(50, 200) - cota = CotaMensal( - militante_id=militante.id, - valor_antigo=valor, - valor_novo=valor * 1.1, - data_alteracao=data_base, - data_vencimento=data_base + timedelta(days=30), - pago=random.choice([True, False]) - ) - db_session.add(cota) - print(f" Cota criada: valor={valor:.2f}, vencimento={data_base + timedelta(days=30)}") - db_session.commit() + try: + print(f"Criando cotas para militante {militante.nome}") + for i in range(quantidade_por_militante): + data_base = datetime.now() - timedelta(days=30 * i) + valor = random.uniform(50, 200) + cota = CotaMensal( + militante_id=militante.id, + valor_antigo=valor, + valor_novo=valor * 1.1, + data_alteracao=data_base, + data_vencimento=data_base + timedelta(days=30), + pago=random.choice([True, False]) + ) + session.add(cota) + session.commit() + except Exception as e: + print(f"Erro ao criar cotas para militante {militante.nome}: {e}") + session.rollback() + continue print("Cotas criadas com sucesso!") def criar_pagamentos(militantes): @@ -273,21 +286,20 @@ def seed_database(): """Função principal para popular o banco de dados com dados fictícios""" print("Populando banco de dados com dados fictícios...") - criar_tipos_pagamento() - criar_tipos_material() - criar_setores() - criar_comites() - criar_roles() - - militantes = criar_militantes(50) - criar_cotas(militantes) - criar_pagamentos(militantes) - criar_materiais_vendidos(militantes) - criar_vendas_jornal(militantes) - criar_assinaturas(militantes) - criar_relatorios() - - print("Dados fictícios criados com sucesso!") + session = SessionLocal() + try: + criar_tipos_pagamento(session) + criar_tipos_material(session) + + militantes = criar_militantes(session, 50) + if militantes: + criar_cotas(session, militantes) + print("Dados fictícios criados com sucesso!") + except Exception as e: + print(f"Erro ao popular banco de dados: {e}") + session.rollback() + finally: + session.close() if __name__ == "__main__": seed_database() \ No newline at end of file