feat: implementacao inicial do sistema LeadRadar
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
from app.models.user import User
|
||||
from app.models.lead import Lead
|
||||
from app.models.lead_interacao import LeadInteracao
|
||||
|
||||
__all__ = ['User', 'Lead', 'LeadInteracao']
|
||||
@@ -0,0 +1,60 @@
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from app.extensions import db
|
||||
|
||||
class Lead(db.Model):
|
||||
__tablename__ = 'leads'
|
||||
|
||||
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||
nome_empresa = db.Column(db.String(255), index=True, nullable=False)
|
||||
ramo_atividade = db.Column(db.String(100), index=True, nullable=False)
|
||||
cep_busca = db.Column(db.String(10), index=True, nullable=False)
|
||||
logradouro = db.Column(db.String(255), nullable=True)
|
||||
bairro = db.Column(db.String(100), nullable=True)
|
||||
cidade = db.Column(db.String(100), index=True, nullable=True)
|
||||
uf = db.Column(db.String(2), nullable=True)
|
||||
telefone = db.Column(db.String(50), nullable=True)
|
||||
telefone_sanitizado = db.Column(db.String(30), index=True, nullable=True)
|
||||
whatsapp_valido = db.Column(db.Boolean, nullable=True, default=True)
|
||||
website = db.Column(db.String(255), nullable=True)
|
||||
google_rating = db.Column(db.Float, default=0.0)
|
||||
total_avaliacoes = db.Column(db.Integer, default=0)
|
||||
google_maps_url = db.Column(db.Text, nullable=True)
|
||||
status_funil = db.Column(db.String(30), default='novo', nullable=False, index=True)
|
||||
tags = db.Column(db.JSON, default=list)
|
||||
notas = db.Column(db.Text, nullable=True)
|
||||
usuario_responsavel_id = db.Column(db.String(36), db.ForeignKey('users.id', ondelete='SET NULL'), nullable=True)
|
||||
criado_em = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
|
||||
atualizado_em = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
|
||||
|
||||
# Relationships
|
||||
interacoes = db.relationship('LeadInteracao', backref='lead', cascade='all, delete-orphan', lazy='dynamic')
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'nome_empresa': self.nome_empresa,
|
||||
'ramo_atividade': self.ramo_atividade,
|
||||
'cep_busca': self.cep_busca,
|
||||
'logradouro': self.logradouro,
|
||||
'bairro': self.bairro,
|
||||
'cidade': self.cidade,
|
||||
'uf': self.uf,
|
||||
'telefone': self.telefone,
|
||||
'telefone_sanitizado': self.telefone_sanitizado,
|
||||
'whatsapp_valido': self.whatsapp_valido,
|
||||
'website': self.website,
|
||||
'google_rating': self.google_rating,
|
||||
'total_avaliacoes': self.total_avaliacoes,
|
||||
'google_maps_url': self.google_maps_url,
|
||||
'status_funil': self.status_funil,
|
||||
'tags': self.tags or [],
|
||||
'notas': self.notas or '',
|
||||
'usuario_responsavel_id': self.usuario_responsavel_id,
|
||||
'usuario_responsavel_nome': self.usuario_responsavel.nome if self.usuario_responsavel else None,
|
||||
'criado_em': self.criado_em.isoformat() if self.criado_em else None,
|
||||
'atualizado_em': self.atualizado_em.isoformat() if self.atualizado_em else None
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Lead {self.nome_empresa} ({self.status_funil})>'
|
||||
@@ -0,0 +1,29 @@
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from app.extensions import db
|
||||
|
||||
class LeadInteracao(db.Model):
|
||||
__tablename__ = 'lead_interacoes'
|
||||
|
||||
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||
lead_id = db.Column(db.String(36), db.ForeignKey('leads.id', ondelete='CASCADE'), nullable=False, index=True)
|
||||
usuario_id = db.Column(db.String(36), db.ForeignKey('users.id', ondelete='SET NULL'), nullable=True, index=True)
|
||||
tipo = db.Column(db.String(50), nullable=False, index=True)
|
||||
descricao = db.Column(db.Text, nullable=False)
|
||||
metadados = db.Column(db.JSON, default=dict)
|
||||
timestamp = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), index=True)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'lead_id': self.lead_id,
|
||||
'usuario_id': self.usuario_id,
|
||||
'usuario_nome': self.usuario.nome if self.usuario else 'Sistema',
|
||||
'tipo': self.tipo,
|
||||
'descricao': self.descricao,
|
||||
'metadados': self.metadados or {},
|
||||
'timestamp': self.timestamp.isoformat() if self.timestamp else None
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<LeadInteracao {self.tipo} lead={self.lead_id}>'
|
||||
@@ -0,0 +1,45 @@
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
# We will import db from extensions, but let's define extensions properly
|
||||
from app.extensions import db, bcrypt
|
||||
|
||||
class User(db.Model):
|
||||
__tablename__ = 'users'
|
||||
|
||||
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||
nome = db.Column(db.String(120), nullable=False)
|
||||
email = db.Column(db.String(180), unique=True, index=True, nullable=False)
|
||||
password_hash = db.Column(db.String(255), nullable=False)
|
||||
role = db.Column(db.String(20), nullable=False, default='user') # 'admin' or 'user'
|
||||
ativo = db.Column(db.Boolean, default=True, nullable=False)
|
||||
criado_em = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
|
||||
atualizado_em = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
|
||||
|
||||
# Relationships
|
||||
leads_responsaveis = db.relationship('Lead', backref='usuario_responsavel', lazy='dynamic')
|
||||
interacoes = db.relationship('LeadInteracao', backref='usuario', lazy='dynamic')
|
||||
|
||||
def set_password(self, password: str):
|
||||
self.password_hash = bcrypt.generate_password_hash(password).decode('utf-8')
|
||||
|
||||
def check_password(self, password: str) -> bool:
|
||||
return bcrypt.check_password_hash(self.password_hash, password)
|
||||
|
||||
def is_admin(self) -> bool:
|
||||
return self.role == 'admin'
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'nome': self.nome,
|
||||
'email': self.email,
|
||||
'role': self.role,
|
||||
'ativo': self.ativo,
|
||||
'criado_em': self.criado_em.isoformat() if self.criado_em else None,
|
||||
'atualizado_em': self.atualizado_em.isoformat() if self.atualizado_em else None
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<User {self.email} ({self.role})>'
|
||||
Reference in New Issue
Block a user