- inits centralizados, READMEs atualizados

- padronizando o nome de get_db_connection e session para get_db_session, para não confundir com session do Flask ou sessoes web

- corrigindo potenciais erros

-- has_permission nao consegue com lazy load carregar permission depois de load_user fechar a conexao, entao joinedLoad com Permission antes de fechar

-- db.rollback não existe caso db = get_db_session() apareça muito depois dentro do try, padronizando antes de try

--- comparar role por nivel (Role.SECRETARIO_GERAL) e nao por nome ("Secretario Geral")

- unificacao de get_otp_qr_code

- mudança de nowutc() para now(UTC) conforme novo padrão
This commit is contained in:
2026-02-20 17:19:15 -03:00
parent 6882b57081
commit 2b1668206d
38 changed files with 1250 additions and 1187 deletions

337
scripts/seed_database.py Normal file
View File

@@ -0,0 +1,337 @@
from datetime import datetime, timedelta
from functions.database import (
Base, Militante, CotaMensal, TipoPagamento, Pagamento,
MaterialVendido, TipoMaterial, VendaJornalAvulso, AssinaturaAnual,
RelatorioCotasMensais, RelatorioVendasMateriais,
Setor, ComiteCentral, Usuario, Role, EmailMilitante, Endereco,
ComiteRegional, Celula, EstadoMilitante, get_db_session
)
import random
from faker import Faker
from werkzeug.security import generate_password_hash
fake = Faker('pt_BR')
def criar_estrutura_organizacional(db):
"""Cria a estrutura organizacional básica"""
print("\nCriando estrutura organizacional...")
# Criar Comitê Central
cc = ComiteCentral(nome="Comitê Central SP")
db.add(cc)
db.flush()
# Criar Comitês Regionais
crs = []
for nome in ["CR São Paulo", "CR ABC", "CR Campinas"]:
cr = ComiteRegional(nome=nome)
db.add(cr)
db.flush()
crs.append(cr)
# Criar Setores para cada CR
setores = []
for cr in crs:
for i in range(2): # 2 setores por CR
setor = Setor(
nome=f"Setor {i+1} - {cr.nome}",
cr_id=cr.id
)
db.add(setor)
db.flush()
setores.append(setor)
# Criar Células para cada Setor
for setor in setores:
for i in range(2): # 2 células por setor
celula = Celula(
nome=f"Célula {i+1} - {setor.nome}",
setor_id=setor.id
)
db.add(celula)
db.commit()
return crs, setores
def criar_tipos_pagamento(db):
"""Cria tipos de pagamento padrão"""
print("\nCriando tipos de pagamento...")
tipos = [
"Dinheiro",
"PIX",
"Cartão de Crédito",
"Cartão de Débito",
"Transferência Bancária"
]
for tipo in tipos:
if not db.query(TipoPagamento).filter_by(descricao=tipo).first():
db.add(TipoPagamento(descricao=tipo))
db.commit()
def criar_tipos_material(db):
"""Cria tipos de material padrão"""
print("\nCriando tipos de material...")
tipos = [
"Jornal",
"Revista",
"Livro",
"Panfleto",
"Cartilha"
]
for tipo in tipos:
if not db.query(TipoMaterial).filter_by(descricao=tipo).first():
db.add(TipoMaterial(descricao=tipo))
db.commit()
def criar_militantes(db, num_militantes, setores):
"""Cria militantes com todos os dados necessários"""
print(f"\nCriando {num_militantes} militantes...")
militantes = []
emails_usados = set()
for i in range(num_militantes):
try:
# Dados básicos
nome = fake.name()
cpf = fake.cpf()
# Criar endereço
endereco = Endereco(
cep=fake.postcode(),
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
)
db.add(endereco)
db.flush()
# Selecionar setor e célula aleatórios
setor = random.choice(setores)
celula = random.choice(db.query(Celula).filter_by(setor_id=setor.id).all())
# Definir responsabilidades
responsabilidades = 0
if random.random() < 0.2: # 20% chance de ser Responsável de Finanças
responsabilidades |= Militante.RESPONSAVEL_FINANCAS
if random.random() < 0.2: # 20% chance de ser Responsável de Imprensa
responsabilidades |= Militante.RESPONSAVEL_IMPRENSA
if random.random() < 0.2: # 20% chance de ser Quadro-Orientador
responsabilidades |= Militante.QUADRO_ORIENTADOR
if random.random() < 0.2: # 20% chance de ser Secretário
responsabilidades |= Militante.SECRETARIO
if random.random() < 0.2: # 20% chance de ser MPS
responsabilidades |= Militante.MPS
if random.random() < 0.2: # 20% chance de ser Tesoureiro
responsabilidades |= Militante.TESOUREIRO
if random.random() < 0.2: # 20% chance de ser MNS
responsabilidades |= Militante.MNS
if random.random() < 0.2: # 20% chance de ser da Juventude
responsabilidades |= Militante.JUVENTUDE
if random.random() < 0.3: # 30% chance de ser Aspirante
responsabilidades |= Militante.ASPIRANTE
print(f"Criando militante {i+1}: {nome}")
# Criar militante com todos os dados
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,
celula_id=celula.id,
responsabilidades=responsabilidades,
estado=random.choice(list(EstadoMilitante))
)
db.add(militante)
db.flush()
# Email único
while True:
email = fake.email()
if email not in emails_usados:
emails_usados.add(email)
break
# Criar email do militante
email_militante = EmailMilitante(
militante_id=militante.id,
endereco_email=email
)
db.add(email_militante)
militantes.append(militante)
db.commit()
except Exception as e:
print(f"Erro ao criar militante {i+1}: {e}")
db.rollback()
continue
return militantes
def criar_cotas(db, militantes):
"""Cria cotas mensais para os militantes"""
print("\nCriando cotas mensais...")
for militante in militantes:
try:
# Criar 12 cotas (1 ano) para cada militante
for i in range(12):
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.add(cota)
db.commit()
except Exception as e:
print(f"Erro ao criar cotas para militante {militante.nome}: {e}")
db.rollback()
def criar_pagamentos(db, militantes):
"""Cria pagamentos para os militantes"""
print("\nCriando pagamentos...")
tipos_pagamento = db.query(TipoPagamento).all()
for militante in militantes:
try:
# Criar entre 3 e 8 pagamentos por militante
for _ in range(random.randint(3, 8)):
tipo = random.choice(tipos_pagamento)
pagamento = Pagamento(
militante_id=militante.id,
tipo_pagamento=tipo.descricao, # Usando a descrição do tipo
valor=random.uniform(50, 500),
data_pagamento=fake.date_between(start_date='-1y', end_date='today')
)
db.add(pagamento)
db.commit()
except Exception as e:
print(f"Erro ao criar pagamentos para militante {militante.nome}: {e}")
db.rollback()
def criar_materiais_vendidos(db, militantes):
"""Cria registros de materiais vendidos"""
print("\nCriando materiais vendidos...")
tipos_material = db.query(TipoMaterial).all()
for militante in militantes:
try:
# Criar entre 2 e 5 materiais vendidos por militante
for _ in range(random.randint(2, 5)):
material = MaterialVendido(
militante_id=militante.id,
tipo_material_id=random.choice(tipos_material).id,
descricao=fake.sentence(),
valor=random.uniform(20, 100),
data_venda=fake.date_time_between(start_date='-1y', end_date='now')
)
db.add(material)
db.commit()
except Exception as e:
print(f"Erro ao criar materiais vendidos para militante {militante.nome}: {e}")
db.rollback()
def criar_vendas_jornal(db, militantes):
"""Cria vendas de jornal avulso"""
print("\nCriando vendas de jornal...")
for militante in militantes:
try:
# Criar entre 2 e 6 vendas de jornal por militante
for _ in range(random.randint(2, 6)):
quantidade = random.randint(1, 10)
valor_unitario = random.uniform(5, 15)
venda = VendaJornalAvulso(
militante_id=militante.id,
quantidade=quantidade,
valor_total=quantidade * valor_unitario,
data_venda=fake.date_time_between(start_date='-1y', end_date='now')
)
db.add(venda)
db.commit()
except Exception as e:
print(f"Erro ao criar vendas de jornal para militante {militante.nome}: {e}")
db.rollback()
def criar_assinaturas(db, militantes):
"""Cria assinaturas anuais"""
print("\nCriando assinaturas anuais...")
tipos_material = db.query(TipoMaterial).all()
for militante in militantes:
try:
# 30% de chance de ter assinatura
if random.random() < 0.3:
data_inicio = fake.date_time_between(start_date='-1y', end_date='now')
assinatura = AssinaturaAnual(
militante_id=militante.id,
tipo_material_id=random.choice(tipos_material).id,
quantidade=random.randint(1, 3),
valor_total=random.uniform(100, 500),
data_inicio=data_inicio,
data_fim=data_inicio + timedelta(days=365)
)
db.add(assinatura)
db.commit()
except Exception as e:
print(f"Erro ao criar assinatura para militante {militante.nome}: {e}")
db.rollback()
def seed_database():
"""Função principal para popular o banco de dados"""
db = get_db_session()
try:
print("Iniciando população do banco de dados...")
# Criar tipos básicos
criar_tipos_pagamento(db)
criar_tipos_material(db)
# Criar estrutura organizacional
crs, setores = criar_estrutura_organizacional(db)
# Criar militantes (30 militantes para teste)
militantes = criar_militantes(db, 30, setores)
# Criar dados financeiros e materiais
criar_cotas(db, militantes)
criar_pagamentos(db, militantes)
criar_materiais_vendidos(db, militantes)
criar_vendas_jornal(db, militantes)
criar_assinaturas(db, militantes)
print("\nBanco de dados populado com sucesso!")
except Exception as e:
print(f"Erro durante a população do banco: {e}")
db.rollback()
finally:
db.close()
if __name__ == "__main__":
seed_database()