feat: versão 1.5 - CRM Beta com leads, funis, campanhas e portal do cliente
This commit is contained in:
42
backend/internal/domain/auth_unified.go
Normal file
42
backend/internal/domain/auth_unified.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package domain
|
||||
|
||||
import "github.com/golang-jwt/jwt/v5"
|
||||
|
||||
// UserType representa os diferentes tipos de usuários do sistema
|
||||
type UserType string
|
||||
|
||||
const (
|
||||
UserTypeAgency UserType = "agency_user" // Usuários das agências (admin, colaborador)
|
||||
UserTypeCustomer UserType = "customer" // Clientes do CRM
|
||||
// SUPERADMIN usa endpoint próprio /api/admin/*, não usa autenticação unificada
|
||||
)
|
||||
|
||||
// UnifiedClaims representa as claims do JWT unificado
|
||||
type UnifiedClaims struct {
|
||||
UserID string `json:"user_id"` // ID do usuário (user.id ou customer.id)
|
||||
UserType UserType `json:"user_type"` // Tipo de usuário
|
||||
TenantID string `json:"tenant_id,omitempty"` // ID do tenant (agência)
|
||||
Email string `json:"email"` // Email do usuário
|
||||
Role string `json:"role,omitempty"` // Role (para agency_user: ADMIN_AGENCIA, CLIENTE)
|
||||
AgencyRole string `json:"agency_role,omitempty"` // Agency role (owner ou collaborator)
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// UnifiedLoginRequest representa uma requisição de login unificada
|
||||
type UnifiedLoginRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// UnifiedLoginResponse representa a resposta de login unificada
|
||||
type UnifiedLoginResponse struct {
|
||||
Token string `json:"token"`
|
||||
UserType UserType `json:"user_type"`
|
||||
UserID string `json:"user_id"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
Role string `json:"role,omitempty"` // Apenas para agency_user
|
||||
AgencyRole string `json:"agency_role,omitempty"` // owner ou collaborator
|
||||
TenantID string `json:"tenant_id,omitempty"` // ID do tenant
|
||||
Subdomain string `json:"subdomain,omitempty"` // Subdomínio da agência
|
||||
}
|
||||
@@ -1,31 +1,41 @@
|
||||
package domain
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CRMCustomer struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
TenantID string `json:"tenant_id" db:"tenant_id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Email string `json:"email" db:"email"`
|
||||
Phone string `json:"phone" db:"phone"`
|
||||
Company string `json:"company" db:"company"`
|
||||
Position string `json:"position" db:"position"`
|
||||
Address string `json:"address" db:"address"`
|
||||
City string `json:"city" db:"city"`
|
||||
State string `json:"state" db:"state"`
|
||||
ZipCode string `json:"zip_code" db:"zip_code"`
|
||||
Country string `json:"country" db:"country"`
|
||||
Notes string `json:"notes" db:"notes"`
|
||||
Tags []string `json:"tags" db:"tags"`
|
||||
IsActive bool `json:"is_active" db:"is_active"`
|
||||
CreatedBy string `json:"created_by" db:"created_by"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
ID string `json:"id" db:"id"`
|
||||
TenantID string `json:"tenant_id" db:"tenant_id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Email string `json:"email" db:"email"`
|
||||
Phone string `json:"phone" db:"phone"`
|
||||
Company string `json:"company" db:"company"`
|
||||
Position string `json:"position" db:"position"`
|
||||
Address string `json:"address" db:"address"`
|
||||
City string `json:"city" db:"city"`
|
||||
State string `json:"state" db:"state"`
|
||||
ZipCode string `json:"zip_code" db:"zip_code"`
|
||||
Country string `json:"country" db:"country"`
|
||||
Notes string `json:"notes" db:"notes"`
|
||||
Tags []string `json:"tags" db:"tags"`
|
||||
LogoURL string `json:"logo_url" db:"logo_url"`
|
||||
IsActive bool `json:"is_active" db:"is_active"`
|
||||
CreatedBy string `json:"created_by" db:"created_by"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
PasswordHash string `json:"-" db:"password_hash"`
|
||||
HasPortalAccess bool `json:"has_portal_access" db:"has_portal_access"`
|
||||
PortalLastLogin *time.Time `json:"portal_last_login,omitempty" db:"portal_last_login"`
|
||||
PortalCreatedAt *time.Time `json:"portal_created_at,omitempty" db:"portal_created_at"`
|
||||
}
|
||||
|
||||
type CRMList struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
TenantID string `json:"tenant_id" db:"tenant_id"`
|
||||
CustomerID *string `json:"customer_id" db:"customer_id"`
|
||||
FunnelID *string `json:"funnel_id" db:"funnel_id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Description string `json:"description" db:"description"`
|
||||
Color string `json:"color" db:"color"`
|
||||
@@ -49,5 +59,77 @@ type CRMCustomerWithLists struct {
|
||||
|
||||
type CRMListWithCustomers struct {
|
||||
CRMList
|
||||
CustomerCount int `json:"customer_count"`
|
||||
CustomerName string `json:"customer_name"`
|
||||
CustomerCount int `json:"customer_count"`
|
||||
LeadCount int `json:"lead_count"`
|
||||
}
|
||||
|
||||
// ==================== LEADS ====================
|
||||
|
||||
type CRMLead struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
TenantID string `json:"tenant_id" db:"tenant_id"`
|
||||
CustomerID *string `json:"customer_id" db:"customer_id"`
|
||||
FunnelID *string `json:"funnel_id" db:"funnel_id"`
|
||||
StageID *string `json:"stage_id" db:"stage_id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Email string `json:"email" db:"email"`
|
||||
Phone string `json:"phone" db:"phone"`
|
||||
Source string `json:"source" db:"source"`
|
||||
SourceMeta json.RawMessage `json:"source_meta" db:"source_meta"`
|
||||
Status string `json:"status" db:"status"`
|
||||
Notes string `json:"notes" db:"notes"`
|
||||
Tags []string `json:"tags" db:"tags"`
|
||||
IsActive bool `json:"is_active" db:"is_active"`
|
||||
CreatedBy string `json:"created_by" db:"created_by"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
type CRMFunnel struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
TenantID string `json:"tenant_id" db:"tenant_id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Description string `json:"description" db:"description"`
|
||||
IsDefault bool `json:"is_default" db:"is_default"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
type CRMFunnelStage struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
FunnelID string `json:"funnel_id" db:"funnel_id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Description string `json:"description" db:"description"`
|
||||
Color string `json:"color" db:"color"`
|
||||
OrderIndex int `json:"order_index" db:"order_index"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
type CRMFunnelWithStages struct {
|
||||
CRMFunnel
|
||||
Stages []CRMFunnelStage `json:"stages"`
|
||||
}
|
||||
|
||||
type CRMLeadList struct {
|
||||
LeadID string `json:"lead_id" db:"lead_id"`
|
||||
ListID string `json:"list_id" db:"list_id"`
|
||||
AddedAt time.Time `json:"added_at" db:"added_at"`
|
||||
AddedBy string `json:"added_by" db:"added_by"`
|
||||
}
|
||||
|
||||
type CRMLeadWithLists struct {
|
||||
CRMLead
|
||||
Lists []CRMList `json:"lists"`
|
||||
}
|
||||
|
||||
type CRMShareToken struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
TenantID string `json:"tenant_id" db:"tenant_id"`
|
||||
CustomerID string `json:"customer_id" db:"customer_id"`
|
||||
Token string `json:"token" db:"token"`
|
||||
ExpiresAt *time.Time `json:"expires_at" db:"expires_at"`
|
||||
CreatedBy string `json:"created_by" db:"created_by"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
}
|
||||
|
||||
@@ -8,14 +8,17 @@ import (
|
||||
|
||||
// User represents a user in the system
|
||||
type User struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
TenantID *uuid.UUID `json:"tenant_id,omitempty" db:"tenant_id"`
|
||||
Email string `json:"email" db:"email"`
|
||||
Password string `json:"-" db:"password_hash"`
|
||||
Name string `json:"name" db:"first_name"`
|
||||
Role string `json:"role" db:"role"` // SUPERADMIN, ADMIN_AGENCIA, CLIENTE
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
TenantID *uuid.UUID `json:"tenant_id,omitempty" db:"tenant_id"`
|
||||
Email string `json:"email" db:"email"`
|
||||
Password string `json:"-" db:"password_hash"`
|
||||
Name string `json:"name" db:"first_name"`
|
||||
Role string `json:"role" db:"role"` // SUPERADMIN, ADMIN_AGENCIA, CLIENTE
|
||||
AgencyRole string `json:"agency_role" db:"agency_role"` // owner or collaborator (only for ADMIN_AGENCIA)
|
||||
CreatedBy *uuid.UUID `json:"created_by,omitempty" db:"created_by"` // Which owner created this collaborator
|
||||
CollaboratorCreatedAt *time.Time `json:"collaborator_created_at,omitempty" db:"collaborator_created_at"` // When collaborator was added
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
// CreateUserRequest represents the request to create a new user
|
||||
|
||||
Reference in New Issue
Block a user