- Adiciona os modelos que faltavam na arquitetura MVC - Corrige relacionamentos de referência cruzada entre modelos - Atualiza script de preparação para criar arquivos __init__.py adequados - Torna o script de preparação executável 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
155 lines
6.1 KiB
Python
155 lines
6.1 KiB
Python
from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, Date, Text, Enum
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime
|
|
import enum
|
|
import secrets
|
|
|
|
from models.entities.base import Base
|
|
|
|
class EstadoMilitante(enum.Enum):
|
|
ATIVO = 'ativo'
|
|
DESLIGADO = 'desligado'
|
|
SUSPENSO = 'suspenso'
|
|
AFASTADO = 'afastado'
|
|
|
|
class Militante(Base):
|
|
__tablename__ = 'militantes'
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
nome = Column(String(100), nullable=False)
|
|
cpf = Column(String(14), unique=True)
|
|
# Novos campos básicos
|
|
titulo_eleitoral = Column(String(20))
|
|
data_nascimento = Column(Date)
|
|
data_entrada_oci = Column(Date)
|
|
data_efetivacao_oci = Column(Date)
|
|
# Campos de contato
|
|
telefone1 = Column(String(15))
|
|
telefone2 = Column(String(15))
|
|
# Relacionamento para múltiplos emails
|
|
emails = relationship("EmailMilitante", back_populates="militante")
|
|
# Endereço
|
|
endereco_id = Column(Integer, ForeignKey('enderecos.id', use_alter=True, name='fk_militante_endereco'))
|
|
endereco = relationship("Endereco", back_populates="militantes")
|
|
# Redes sociais
|
|
redes_sociais = relationship("RedeSocial", back_populates="militante")
|
|
# Campos profissionais
|
|
profissao = Column(String(100))
|
|
regime_trabalho = Column(String(50)) # CLT, Estatutário, etc.
|
|
empresa = Column(String(100))
|
|
contratante = Column(String(100)) # Para terceirizados
|
|
# Campos acadêmicos
|
|
instituicao_ensino = Column(String(100))
|
|
tipo_instituicao = Column(String(20)) # Federal, Estadual, etc.
|
|
# Campos sindicais
|
|
sindicato = Column(String(100))
|
|
cargo_sindical = Column(String(50))
|
|
dirigente_sindical = Column(Boolean)
|
|
central_sindical = Column(String(100))
|
|
# Responsável pelo cadastro
|
|
registrado_por = Column(Integer, ForeignKey('militantes.id', use_alter=True, name='fk_militante_registrado_por'))
|
|
# Campos existentes
|
|
celula_id = Column(Integer, ForeignKey('celulas.id', use_alter=True, name='fk_militante_celula'))
|
|
responsabilidades = Column(Integer, default=0)
|
|
otp_secret = Column(String(32))
|
|
temp_token = Column(String(64))
|
|
temp_token_expiry = Column(DateTime)
|
|
# Novo campo para Quadro-Orientador
|
|
quadro_orientador = Column(Boolean, default=False)
|
|
# Campos para Aspirante
|
|
aspirante = Column(Boolean, default=True) # Por padrão, todo novo militante é aspirante
|
|
data_inicio_aspirante = Column(DateTime, default=datetime.utcnow)
|
|
avaliacao_aspirante = Column(Text)
|
|
data_avaliacao_aspirante = Column(DateTime)
|
|
|
|
# Campos para estado do militante
|
|
estado = Column(Enum(EstadoMilitante), default=EstadoMilitante.ATIVO)
|
|
data_desligamento = Column(DateTime)
|
|
motivo_desligamento = Column(Text)
|
|
|
|
# Relacionamentos existentes
|
|
cotas_mensais = relationship("CotaMensal", back_populates="militante")
|
|
pagamentos = relationship("Pagamento", back_populates="militante")
|
|
materiais_vendidos = relationship("MaterialVendido", back_populates="militante")
|
|
vendas_jornais_avulsos = relationship("VendaJornalAvulso", back_populates="militante")
|
|
vendas_jornais = relationship("VendaJornal", back_populates="militante", foreign_keys="[VendaJornal.militante_id]")
|
|
assinaturas = relationship("AssinaturaJornal", back_populates="militante", foreign_keys="[AssinaturaJornal.militante_id]")
|
|
celula = relationship("Celula", back_populates="militantes", foreign_keys=[celula_id])
|
|
comprovantes = relationship("Comprovante", back_populates="militante")
|
|
|
|
# Constantes para responsabilidades
|
|
SECRETARIO = 1
|
|
TESOUREIRO = 2
|
|
IMPRENSA = 4
|
|
MNS = 8
|
|
MPS = 16
|
|
JUVENTUDE = 32
|
|
QUADRO_ORIENTADOR = 64
|
|
ASPIRANTE = 128
|
|
RESPONSAVEL_FINANCAS = 256
|
|
RESPONSAVEL_IMPRENSA = 512
|
|
|
|
@staticmethod
|
|
def get_responsabilidades_list():
|
|
return [
|
|
(Militante.SECRETARIO, "Secretário"),
|
|
(Militante.TESOUREIRO, "Tesoureiro"),
|
|
(Militante.IMPRENSA, "Imprensa"),
|
|
(Militante.MNS, "MNS"),
|
|
(Militante.MPS, "MPS"),
|
|
(Militante.JUVENTUDE, "Juventude"),
|
|
(Militante.QUADRO_ORIENTADOR, "Quadro-Orientador"),
|
|
(Militante.ASPIRANTE, "Aspirante"),
|
|
(Militante.RESPONSAVEL_FINANCAS, "Responsável de Finanças"),
|
|
(Militante.RESPONSAVEL_IMPRENSA, "Responsável de Imprensa")
|
|
]
|
|
|
|
def set_responsabilidades(self, resp_list):
|
|
"""
|
|
Define as responsabilidades do militante
|
|
resp_list: lista de inteiros representando as responsabilidades
|
|
"""
|
|
self.responsabilidades = sum(resp_list)
|
|
|
|
def get_responsabilidades(self):
|
|
"""
|
|
Retorna lista de responsabilidades ativas
|
|
"""
|
|
resp = []
|
|
for valor, nome in self.get_responsabilidades_list():
|
|
if self.responsabilidades & valor:
|
|
resp.append(nome)
|
|
return resp
|
|
|
|
def generate_temp_token(self):
|
|
"""
|
|
Gera um token temporário para acesso ao QR code
|
|
"""
|
|
self.temp_token = secrets.token_urlsafe(32)
|
|
self.temp_token_expiry = datetime.now() + timedelta(hours=48)
|
|
return self.temp_token
|
|
|
|
def generate_username(self):
|
|
"""Gera um nome de usuário único baseado no primeiro nome e um código"""
|
|
from sqlalchemy import func
|
|
from services.database_service import DatabaseService
|
|
|
|
db = DatabaseService.get_db_connection()
|
|
try:
|
|
# Pega o primeiro nome
|
|
primeiro_nome = self.nome.split()[0].lower()
|
|
|
|
# Importação local para evitar dependência circular
|
|
from models.entities.usuario import Usuario
|
|
|
|
# Conta quantos usuários já existem com esse prefixo
|
|
count = db.query(func.count(Usuario.id)).filter(
|
|
Usuario.username.like(f"{primeiro_nome}%")
|
|
).scalar()
|
|
|
|
# Gera o código (número sequencial)
|
|
codigo = str(count + 1).zfill(3)
|
|
|
|
return f"{primeiro_nome}{codigo}"
|
|
finally:
|
|
db.close() |