🧭 Service Blueprint · Painel do Vendedor

Como o Rally funciona por dentro

Para cada tela, o caminho completo: o que você faz e vê → o que o sistema faz → o que vai pro Mercado Livre. Tela por tela, do clique ao resultado.

👤 Você faz/vê ⚙️ Sistema faz 🌐 Externo (ML / Pix)
📋 Fluxos 🧠 Ver como grafo

Mapa do painel — 69 fluxos

📝 01
Cadastro
🔌 02
Conectar conta Mercado Livre
📊 03
Dashboard
🤖 04
Assistente de IA
📦 05
Anúncios
🧾 06
Dados Fiscais
🛒 07
Vendas
👥 08
Clientes
💬 09
Comunicação
📣 10
Marketing (Mercado Ads)
📈 11
Performance
🩺 12
Saúde da Loja
🏖️ 13
Modo Férias
🚚 14
Transportadoras
💰 15
Fechamentos PIX
🏪 16
Minha Vitrine
🌐 17
Vitrine Pública
🖼️ 18
Produtos da Vitrine
📝 19
Blog da Loja
🎓 20
Cursos
21
Check-in Diário
🎥 22
Lives & Eventos
✈️ 23
Grupos Telegram
🧰 24
Ferramentas
🔭 25
Pesquisa de Mercado
📷 26
Checar Fotos
27
Prompts de IA
🧩 28
Plugins & Extensão
📰 29
Blog Oficial
🤝 30
Afiliados
🚀 31
Campanhas
🧾 32
Extrato
⚙️ 33
Configurações
💳 34
Meu Plano
🛒 35
Ativar a Loja com checkout
💳 36
Comprar na vitrine (checkout rápido)
💸 37
Pagamento da loja (PIX, Mercado Pago, na entrega)
🚚 38
Frete + Etiqueta da loja
📦 39
Gerenciar pedidos + recuperar carrinho
40
Avaliações + Produto de fornecedor (drop) na loja
🏆 41
Monitor de Catálogo + Precificação IA
💹 42
Relatório Financeiro
🧾 43
NF-e Automática
44
Uber Direct — Entrega Express
🏭 45
Dashboard do Fornecedor
📦 46
Catálogo do Fornecedor
🛍️ 47
Pedidos Drop
💰 48
Financeiro do Fornecedor
🔗 49
Integrações do Fornecedor
📋 50
Dashboard do Gerente
👥 51
Carteira de Vendedores (GC)
📊 52
Relatórios GC
📦 53
Produtos & Estoque
🎁 54
Kits & Combos
📊 55
Margem por SKU
56
Macros
🚚 57
LogManager (Flex)
🛍️ 58
TikTok Shop
🛍️ 59
Shopee
🛍️ 60
Magalu
🎟️ 61
Cupons da Loja
🏆 62
Meu Pódio
💬 63
Telegram
64
Gestão Flex
📣 65
Broadcast (Gerente)
🎟️ 66
Cupons em Massa
📈 67
Evolução dos Anúncios
📊 68
Financeiro do Gerente
📡 69
Vendas ao Vivo (Live)
Começando
01

Cadastro

Do clique em "Criar conta" até estar logado no painel — direto ou por link de indicação.

/registro · clique pra abrir (já logado)
Tela real de Cadastro 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa rallydevendas.com.br/registro OU chega por um link de indicação de um parceiro.
2Preenche e-mail, senha, nome, WhatsApp e nacionalidade (detectada pela localização).
3Clica em "Criar conta".
4Cai direto no painel já logado — sem etapa bloqueante de e-mail.
o sistema reage por baixo
⚙️ O sistema faz
Valida
Confere o token de segurança e os dados; captura nacionalidade e país fiscal.
Cria
Grava o usuário com senha criptografada.
Vincula
Se veio por indicação, conecta vendedor e parceiro automaticamente (vira comissão pro indicador).
Sessão
Inicia a sessão e registra o cadastro para auditoria.
Avisa
Notifica o admin do novo cadastro por Telegram.
⚠️ AtençãoE-mail duplicadoLimite de tentativas (anti-fraude)
02

Conectar conta Mercado Livre

Conectar sua conta do Mercado Livre com segurança para sincronizar anúncios e vendas. A conexão parte de /lojas; /contas/ml/connect é o endpoint OAuth interno (não é tela).

/lojas · clique pra abrir (já logado)
Tela real de Conectar conta Mercado Livre 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Vai em Lojas → clica "Conectar Mercado Livre".
2Faz login no ML e autoriza o acesso (leitura e escrita).
3Volta pro Rally já com a conta conectada (nome e reputação aparecem).
o sistema reage por baixo
⚙️ O sistema faz
Valida
Confere se você está logado e se o plano permite mais contas.
Protege
Gera um código de segurança único (PKCE) pra ninguém interceptar a conexão.
Troca
Recebe a autorização do ML e troca por um acesso permanente, renovado sozinho a cada 6h.
Criptografa
Guarda o acesso criptografado (AES-256) — o token nunca fica em texto puro.
Indexa
Cria um índice rápido pra receber avisos de venda em tempo real.
🌐 Vai pro Mercado Livre / Pix
Autorização + troca de token no Mercado LivreConsulta seus dados de vendedor (nome, reputação)
⚠️ AtençãoToken expira a cada 6h (renova sozinho)Conta já conectada em outro usuário é recusada
Início
03

Dashboard

Fornecer ao vendedor uma visão centralizada de seu desempenho com KPIs, checklist onboarding, avisos de ação e atalhos rápidos.

/dashboard / /api/widgets/open-orders · clique pra abrir (já logado)
Tela real de Dashboard 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa o painel pelo menu 'Início > Dashboard' ou abre /dashboard
2Visualiza seu progresso em cards-destaque: faturamento hoje, pedidos da semana, produtos/anúncios, faturamento do mês
3Verifica 3 alertas principais: pedidos Drop a pagar, anúncios sem vincular, contas ML desconectadas
4Completa itens do checklist onboarding (foto, WhatsApp, CPF, conexão ML, colaborador, primeiro anúncio)
5Consulta as notificações recentes e aciona atalhos rápidos (criar produto, novo anúncio, conectar ML, calcular preço, clonar anúncio, estoque, pedidos)
6Acompanha seu gráfico de receita (14 dias vs período anterior) e interage com seções colapsáveis (Gamificação, Pedidos, Gráfico, Ações Rápidas)
o sistema reage por baixo
⚙️ O sistema faz
Autentica
Valida que o usuário está logado e perfil preenchido. Se expirou trial gratuito, bloqueia acesso.
Carrega
Busca métricas do vendedor: receita, pedidos, anúncios, saldo da carteira, contas ML vinculadas e seus status.
Compara
Calcula deltas de receita e pedidos (semana vs semana anterior, mês vs mês anterior) para mostrar crescimento.
Cria KPIs
Monta 4 cards: faturamento hoje, pedidos semana, produtos/anúncios, faturamento mês com sub-métricas e progresso.
Verifica alertas
Identifica: custos Drop pendentes, anúncios desvinculados e contas com token expirado/revogado.
Monta checklist
Retorna 7 etapas onboarding com status (feito/pulado): foto, WhatsApp, CPF, conexão ML, colaborador, sobre você, anúncio.
Renderiza
Compõe a página com hero orientado por valor (Design Language v2), seções colapsáveis, notificações e atalhos contextuais.
⚠️ AtençãoContas ML com token expirado/revogado aparecem em alerta; vendedor deve reconectar via /contas/ml/connect para evitar pausa na sincronia de pedidos.Anúncios sem produto vinculado (unlinked) bloqueiam visibilidade completa; redirecionam para /central/anuncios.Usuários sem conta ML conectada veem CTA em destaque com wizard; sem ao menos uma loja, alguns widgets não carregam (crescimento, gráfico).
04

Assistente de IA

Assistente conversacional RAG em tempo real — responde perguntas sobre vendas, anúncios e reputação com dados reais do ML em segundos, usando sua chave de IA (BYOK: Claude, Gemini ou OpenAI) sem cobrar créditos do Rally.

/concierge /perfil/ia /conectar-ia · clique pra abrir (já logado)
Tela real de Assistente de IA 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1No painel, clique em 'Assistente IA' no menu lateral (só aparece se configurou sua chave). A tela mostra histórico de conversas, seletor de modelo e dicas de uso.
2Cole sua chave em Perfil › Inteligência Artificial. Onde criar (Gemini é grátis): aistudio.google.com/apikey → 'Create API key' → chave AIza. Claude: console.anthropic.com/settings/keys · OpenAI: platform.openai.com/api-keys
3Selecione o modelo (Claude Sonnet, Gemini 2.5 Flash, etc.) — sistema faz fallback automático para chave do sistema se BYOK não configurada.
4Digite sua pergunta em português: 'Qual meu melhor anúncio?', 'Quantos pedidos tive essa semana?', 'Como criar um anúncio?' — a IA responde em segundos com contexto real dos seus dados.
5Para editar títulos/descrições de anúncios, use a IA de edição embutida na Central de Anúncios — também usa BYOK sem cobrar créditos.
6Histórico de conversas fica salvo no painel — cada sessão mostra perguntas anteriores e respostas para consulta posterior.
o sistema reage por baixo
⚙️ O sistema faz
autentia
Valida se o usuário está logado; bloqueia acesso a /concierge se não tiver BYOK ativo (redireciona para gate de configuração).
carrega
Recupera histórico de solicitações anteriores do usuário (JSON persistente em storage/concierge_requests.json) — mais recentes primeiro.
processa-entrada
Recebe mensagem do vendedor, valida tamanho (máx 2000 caracteres), anti-flood (20 segundos entre envios). Processamento é SÍNCRONO — sem fila.
RAG-contexto
Monta contexto RAG em tempo real: vendas recentes, anúncios ativos, reputação atual, perguntas abertas, saldo de créditos — dados frescos por usuário.
resolve-chave
Se BYOK ativo: carrega chave criptografada (AES-256-GCM) e descriptografa. Fallback: chave do sistema (Claude/Gemini). Nenhum crédito consumido em BYOK.
gera-resposta
Envia ao Claude ou Gemini com contexto RAG completo; IA responde em streaming (tokens aparecem à medida que chegam). Sugere ações navegáveis (abrir wizard, ir para anúncio).
persiste
Salva par pergunta+resposta no histórico local (IaChatHistoryService) — listado na tela em próximas visitas. Nenhum webhook ou e-mail — resposta está na tela.
🌐 Vai pro Mercado Livre / Pix
POST para Claude/Gemini/OpenAI com pergunta + contexto RAG (vendas, reputação, anúncios) — usa chave BYOK ou do sistema.Dados do ML são PRÉ-CARREGADOS via RAG antes de chamar a IA (sem chamada ML em tempo real durante a resposta).
⚠️ AtençãoSem BYOK e sem chave do sistema configurada: /concierge exibe gate de ativação. Configure em Perfil > Inteligência Artificial.RAG usa dados do cache local (ml_orders, announcements) — pedidos sincronizados há >1h podem não aparecer no contexto. Forçar sync antes de perguntas sobre dados recentes.Modelo selecionado precisa ter chave BYOK válida. Se retornar 429/401, trocar modelo (Gemini 2.5 Flash é gratuito com cota generosa).
Mercado Livre
05

Anúncios

O vendedor publica, edita e clona seus anúncios no Mercado Livre de forma centralizada, sincronizando dados em tempo real com a plataforma ML.

/central/anuncios /anuncios/criar /anuncios/{id}/editar/clonar · clique pra abrir (já logado)
Tela real de Anúncios 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa a Central de Anúncios e vê a lista de todos seus anúncios ativos, pausados ou encerrados no Mercado Livre, filtrado por conta e status
2Clica em 'Criar novo anúncio' e passa por um assistente (wizard) visual: seleciona um produto do catálogo Rally, escolhe a conta ML, marca opções de frete e logística, preenche atributos obrigatórios e valida antes de publicar
3Ao publicar, o Rally envia o anúncio (fotos, título, descrição, preço) ao Mercado Livre via API; o anúncio fica ativo imediatamente e aparece na lista com status 'active'
4Clica em um anúncio para editar: ajusta preço, estoque, descrição, fotos ou status (pausar/retomar/encerrar) — o Rally sincroniza as mudanças com o ML em tempo real
5Usa 'Clonar' para duplicar um anúncio existente para outras contas ML, com opção de ajustar preço e saltar itens pausados
6Consulta o histórico de alterações de cada anúncio e verifica a saúde (score, restrições, elegibilidade para catálogo) diretamente na Central
7Acessa a aba 'Catálogo' para monitorar o Buy Box dos anúncios em catálogo: vê posição atual, concorrentes e preço vencedor em tempo real
8Clica em 'Aplicar agora' para ajustar o preço ao valor vencedor do Buy Box com 1 clique, ou usa o botão IA (ícone robô) para receber sugestão de preço com justificativa via BYOK
o sistema reage por baixo
⚙️ O sistema faz
Redirecionar
GET /anuncios redireciona permanentemente (301) para /central/anuncios — consolidação da listagem
Carregar
Central carrega anúncios ao vivo do Mercado Livre: faz autenticação OAuth, obtém token fresco, chama GET /users/{mluid}/items?status={filtro} para listar por status (active/paused/closed/under_review)
Filtrar
Aplica filtros avançados: por conta, status, score, logística (Full/Flex/Standard), catálogo vs. tradicional, tipo de listagem (premium/clássica) — tudo via JavaScript no client
Criar
Wizard POST /anuncios coleta produto local + conta ML + atributos obrigatórios, valida com /api/ml/rules/dry-run, sobe fotos (até 6 comprimidas + mais via segunda chamada), publica via POST /items ao ML
Editar
POST /anuncios/{id}/editar faz pre-flight (verifica se está em revisão/encerrado/com vendas), filtra campos bloqueados, envia PUT /items/{ml_id} com mudanças permitidas; se em revisão, aceita só descrição (PUT /items/{id}/description)
Publicar
MlPublisher retry automático (até 4 tentativas): ajusta payload conforme erros ML, descarta campos inválidos, sobe fotos antes do POST /items, posta descrição após criação de item
Clonar
POST /anuncios/{id}/clonar-simples dispara CloneJobService para cada conta destino: cria novo anúncio com mesmo produto e dados, mantém histórico de origem em drop_origin
🌐 Vai pro Mercado Livre / Pix
POST /items — publica novo anúncio com título, descrição, preço, estoque, fotos, atributos, frete e logísticaPUT /items/{id} — atualiza preço, estoque, status ou detalhes do anúncio existente; bloqueado se anúncio está em revisão ou tem vendas em certas categoriasPUT /items/{id}/description — atualiza só descrição quando o anúncio está sob revisão ML (under_review)GET /users/{mluid}/items?status={status}&offset={offset} — lista anúncios da conta: ativos, pausados, encerrados ou em revisão; paginada com 50 itens por pagePOST /pictures — carrega fotos individuais e retorna IDs para referenciar no anúncioGET /items/{id} — sincroniza dados do anúncio (marketplace_data): status atual, vendas, visitas, saúde, logística, categoria
⚠️ AtençãoAnúncios em revisão (under_review) — só descrição é editável; tentar editar outros campos retorna erro ML 'item_status_change_not_allowed' e trava o formulárioAnúncios com vendas (has_bids=true) em categorias restritas — campo título, categoria e tipo de listagem ficam travados; ML recusa PUT. Usuário vê aviso 'anúncio com vendas' ao abrir ediçãoLimite de 6 fotos na primeira chamada — Rally faz segunda chamada POST /pictures + PUT para fotos extras (6-12); falha de upload não bloqueia publicação, mas anúncio fica sem fotos completas
06

Dados Fiscais

Permitir que o vendedor configure NCM, CEST e origem dos produtos para destravar emissão automática de Notas Fiscais Eletrônicas.

Tela real de Dados Fiscais 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acesse o menu 'Dados Fiscais' (grupo Mercado Livre) no painel
2Veja a lista de anúncios dividida em: ⚠ Sem NCM, ✓ Com NCM e Total
3Selecione um ou mais anúncios clicando nos checkboxes e clique em 'Editar Fiscais em Massa'
4Preencha os campos obrigatórios (NCM) e opcionais (CEST, CSOSN/CST, Origem) no modal
5O sistema valida o NCM em tempo real contra a tabela TIPI e mostra se é válido
6Clique em 'Aplicar' para enviar os dados selecionados ao Mercado Livre e gerar as NF-es
o sistema reage por baixo
⚙️ O sistema faz
busca
Sistema carrega todos os anúncios do vendedor e calcula totalizadores (com NCM, sem NCM, total)
filtra
Agrupa anúncios por status de completude fiscal — exibe apenas os solicitados (incomplete, complete ou all)
valida
Quando vendedor digita NCM, sistema faz consulta ao Brasil API para confirmar se o código existe na tabela TIPI
monta
Prepara payload com dados fiscais (ncm, cest, csosn, cst, origin_type) dentro de tax_information
envia
Faz PUT para Mercado Livre em /items/fiscal_information/{item_id} com token OAuth da conta conectada
persiste
Salva resposta do ML localmente em announcements.marketplace_data.tax_information com timestamp sync
notifica
Se sucesso em lote, envia notificação ao vendedor via Telegram com contagem de anúncios atualizados
🌐 Vai pro Mercado Livre / Pix
GET https://brasilapi.com.br/api/ncm/v1/{ncm} — valida NCM contra TIPI (sem autenticação)PUT https://api.mercadolibre.com/items/fiscal_information/{item_id} — envia dados fiscais ao Mercado Livre (requer token OAuth do vendedor)
⚠️ AtençãoML não retorna NCM/CEST via API — dados são cadastrados apenas pelo vendedor; sem NCM correto, o anúncio fica bloqueado em 'invoice_pending' e não gera NF-eValidação NCM é apenas verificação de existência contra TIPI; dados financeiros (CSOSN/CST) ainda exigem conferência manual pela contabilidade do vendedor para consistência com regime tributárioRate limiting: aplicação em lote aguarda 150ms entre cada PUT (proteção contra throttling do ML); lotes de 500+ anúncios podem levar minutos
07

Vendas

Visualizar, filtrar e gerenciar vendas do Mercado Livre — desde a criação do pedido até a entrega — acompanhando etiquetas, notas fiscais e rastreio de envio.

Tela real de Vendas 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Vendedor acessa menu Painel > Vendas (no grupo Mercado Livre) e cai em /central/vendas
2Vê uma lista de pedidos com filtros por data, status, conta ML e busca por produto/comprador; KPIs mostram total de vendas, faturamento total, vendas e receita de hoje
3Clica em um pedido para ver detalhe — status, comprador, endereço, número de rastreio; visualiza timeline com eventos (pedido criado, pagamento confirmado, postado, entregue)
4Após o pagamento, baixa etiqueta de envio via botão 'Etiqueta' (entra /ml/etiqueta?ship_id=X) e imprime
5Digita ou escaneia o número de rastreio na etiqueta no sistema do Mercado Livre para atualizar o status
6Acessa /ml/nf para baixar a Nota Fiscal emitida (ou /pedidos/declaracao se for CPF sem NF); acompanha envio via aba 'Envios & Rastreio' que mostra carrier, datas e status em tempo real
o sistema reage por baixo
⚙️ O sistema faz
sincronizar
Sistema sincroniza pedidos via API do Mercado Livre a cada webhook ou cron, consultando os endpoints /orders/search (filtros: paid, confirmed, payment_in_process, cancelled) e /shipments/{id} para obter status, datas e dados do transportista.
armazenar
Todos os dados de vendas são salvos em ml_orders.json local (banco de dados por usuário) com campos: order_id, status, date_created, date_closed, date_shipped, itens, comprador, envio, rastreio e valores (total_amount, comissão).
listar
Ao abrir /central/vendas, carrega os pedidos do JSON local, aplica filtros (data, status, conta, busca), pagina em 50 itens e calcula KPIs (total de vendas, faturamento total, hoje).
enriquecer
Para cada pedido, busca a foto do produto no banco local de anúncios; conecta o account_id à conta ML (nickname) para exibir em qual loja foi vendido (suporta vendedor com múltiplas contas).
detalhar
Ao clicar em /pedidos/{id}, carrega o registro, constrói uma timeline com 5-6 marcos (pedido criado, pagamento confirmado, envio gerado, postado, entregue, cancelado) e calcula prazos (73h para postar após pagamento, alertas de atraso em reputação).
etiqueta
Via /ml/etiqueta?ship_id=X, valida o status+substatus do envio (a etiqueta só existe em ready_to_ship: ready_to_print/printed/in_hub) e baixa o PDF da ML — inclusive Flex (self_service), que sai imediato. Captura proativa: webhook + cron pré-baixam a etiqueta assim que fica pronta, então abre instantânea do cache. Suporta download em lote.
rastreio
Exibe número de rastreio + carrier (Correios, Loggi, etc) vindo do shipment; para Flex (LogBG/Fretecentro), integra webhook de transportista que atualiza status em tempo real com GPS.
🌐 Vai pro Mercado Livre / Pix
GET /orders/search?seller={mlUserId}&order.status=paid,confirmed,payment_in_process,cancelled — busca todas as vendas com status ativoGET /shipments/{shipmentId} — obtém detalhes do envio (status, tracking_number, carrier, logistic_type, receiver_address)GET /shipments/{shipmentId}/label — baixa etiqueta em PDF/ZPL para impressão (via LabelService)GET /invoices/{orderId} — tenta buscar NF-e emitida (se houver CNPJ no vendedor)
⚠️ AtençãoStatus pode ficar desatualizado se webhook do ML falhar — existe re-sync forçada (force=true) para pedidos parados 72h+; vendedor vê 'Enviado' local mas ML ainda diz 'Preparando'Etiqueta só existe quando o ML libera (ready_to_ship). O botão de download só aparece quando ela está REALMENTE pronta — antes disso o sistema mostra o estado certo (Aguardando ML / Aguardando NF / Despachado / Entregue) em vez de um botão que dá erro. Para o que ainda não saiu, há 'Pedir etiqueta ao vendedor' por WhatsApp. Cross-docking (xd_drop_off) pode segurar horas — um monitor diário avisa se uma etiqueta pronta parar de vir.NF-e só aparece para vendedores com CNPJ que emitiram via integração ou automático ML; para CPF ou sem integração, oferece Declaração de Conteúdo (PDF simples) como fallback
08

Clientes

Consultar e enriquecer a base de compradores do Mercado Livre com dados pessoais (nome real, telefone, CPF) via API FonteData ou BigDataCorp, mantendo histórico de contatos (follow-ups).

/clientes /clientes/{ownerId}/{id}/clientes/export · clique pra abrir (já logado)
Tela real de Clientes 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1O vendedor acessa o menu Clientes no painel e vê a lista de todos os compradores que fizeram pedidos no Mercado Livre, filtrados por nome, tag, sexo, classe social e ordenados por recência, valor ou quantidade de pedidos
2Clica em um comprador para ver seu perfil completo (nome, apelido, telefone, e-mail, endereço, pedidos recentes, histórico de contatos e dados enriquecidos como idade, profissão, classe econômica)
3Edita o perfil manualmente (nome, telefones, e-mails, tags, aniversário, notas) ou clica em Enriquecer para buscar dados reais do CPF na FonteData (R$ 1,06/consulta, descontos em volume)
4Consulta e seleciona o resultado encontrado para preencher automaticamente telefones, e-mails, endereço, classe social, renda, profissão e idade
5Registra follow-ups (ligação, mensagem, e-mail, visita) com data e nota para manter histórico de contatos com cada comprador
6Exporta a base inteira em CSV, XLSX ou TXT (respeitando filtros ativos) para análise em planilha ou importação em CRM externo
o sistema reage por baixo
⚙️ O sistema faz
Sincroniza
Importa automaticamente compradores do Mercado Livre cada vez que há novo pedido (buyer_ml_id como chave de deduplicação). Campos protegidos (nome, telefone, e-mail, tags, aniversário, notas) nunca são sobrescritos pelo auto-sync.
Autenticação
Vendedor vê só seus clientes; gerente vê dos seus vendedores; admin vê todos. Acesso por role na sessão.
Filtra
Busca em tempo real por nome/apelido/e-mail/telefone, agrupa por tags, filtra por sexo/classe (dados enriquecidos) e ordena por data/valor/quantidade.
Enriquece
FonteData (CPF) ou BigDataCorp (nome+CEP) consultam base pública e retornam nome real, telefones com WhatsApp, e-mails, endereço, sexo, idade, profissão, classe social e signo. Cache local: se já enriquecido, devolve sem cobrar novamente.
Edita
Salva manualmente nome, lista de telefones/e-mails, tags, aniversário (DD/MM ou DD/MM/AAAA), notas (máx 1000 chars). Registra quem editou (autor, role, timestamp) no log de auditoria (últimas 60 mudanças).
Follow-ups
Adiciona notas de contato com tipo (ligação/mensagem/e-mail/visita/outro), data (padrão=hoje) e descrição. Remove por ID. Exibe mais recentes primeiro.
Exporta
Monta CSV/TXT/XLSX com 20 colunas (nome, CPF, telefones, e-mails, endereço, classe, renda, profissão, idade, sexo, signo, aniversário, tags, contagem de pedidos, total gasto, última compra, loja, vendedor). Respeita todos os filtros aplicados. XLSX gerado com ZipArchive sem dependências externas. BOM UTF-8 em todos os formatos.
🌐 Vai pro Mercado Livre / Pix
POST https://app.fontedata.com/api/v1/consulta/cadastro-pf-plus (X-API-Key header) — busca por CPF (11 dígitos) e retorna nome, telefones com tipo/operadora/WhatsApp, e-mails, endereço, profissão (CBO), classe social, renda estimada, idade, sexo, aniversário, signo e saldo restante em R$POST https://plataforma.bigdatacorp.com.br/people (headers: TokenId, AccessToken) — busca por nome + CEP e retorna lista com até 5 resultados (nome, CPF, telefones, e-mails). Query format: 'name:NOME address_zipcode:CEP'
⚠️ AtençãoFonteData e BigDataCorp usam modelo de crédito (BYOK: Bring Your Own Key). Cada consulta FonteData custa ~R$ 1,06. Saldo consultado e cacheado localmente. Se saldo insuficiente, exibe URL pra top-up.Campos enriquecidos (class, renda, profissão, idade, sexo, signo) ficam no campo enriched[] e são consultados na view (show.php) — a exportação também os inclui.CPF é campo sensível (LGPD). Só é consultado se preenchido manualmente pelo vendedor; nunca é enviado a BigDataCorp (nome+CEP é alternativa). Log de auditoria (edit_log) registra todas as mudanças manuais.
09

Comunicação

Centralizar e responder perguntas, avaliações, mensagens pós-venda, reclamações e devoluções do Mercado Livre em um único painel por aba.

Tela real de Comunicação 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa a Central de Comunicação no menu lateral do painel
2Seleciona uma aba: Perguntas, Avaliações, Mensagens, Reclamações ou Devoluções
3Filtra por conta Mercado Livre conectada ou visualiza todas as contas
4Para Perguntas e Avaliações: responde usando templates rápidos ou texto livre; sistema marca como respondida e publica na ML
5Para Mensagens: abre thread conversa clicando no item, lê histórico completo, responde texto ou envia mídia (imagem/vídeo)
6Para Reclamações: verifica motivo e etapa, responde para resolver ou escala para mediação ML; para Devoluções: monitora status (aberta/reembolsada/fechada)
o sistema reage por baixo
⚙️ O sistema faz
Renderiza
Carrega 5 abas (Perguntas, Avaliações, Mensagens, Reclamações, Devoluções) conforme permissões do plano do usuário; exibe seletor de contas ML ativas
Busca
Chama API Mercado Livre para sincronizar dados: perguntas não respondidas, avaliações, threads de conversa, reclamações abertas/fechadas, devoluções em processamento
Filtra
Aplica filtros na tela: status de resposta (perguntas/avaliações), conta selecionada, período (últimos 90 dias)
Notifica
WhatsApp transacional via MlEventWaNotifier para pergunta nova, mensagem pós-venda, reclamação (afeta reputação), devolução; sincronização de digest 14h para gerentes/fornecedores/admins
Responde
POST para Mercado Livre: resposta de pergunta (até 2000 caracteres), reply em conversa (com suporte a mídia), mensagem em reclamação, resposta avaliação; sistema publica direto na ML
Escalona
Para reclamações abertas: envia mediation request para Mercado Livre; sistema rastreia estágio (buyer_response, seller_response, mediation_accepted) e deadline
Exporta
CSV/TXT de cada aba contendo: perguntas (ID, texto, data, status), mensagens (pack, unread, data), reclamações (ID, motivo, etapa, prazo), devoluções (pedido, motivo, status), avaliações (rating, resposta, data)
🌐 Vai pro Mercado Livre / Pix
GET /questions/search (Perguntas não respondidas com status=UNANSWERED ou todas com status=ANSWERED)POST /questions/{question_id}/answers (Enviar resposta de pergunta)POST /questions/{question_id}/hide (Ocultar pergunta como spam)DELETE /questions/{question_id} (Deletar pergunta permanentemente)GET /reviews (Avaliações de itens publicados, com rating aggregation: positive/neutral/negative)POST /reviews/{review_id}/answer (Responder avaliação)GET /messages/packs (Threads de conversa pós-venda com histórico)POST /messages/packs/{pack_id}/sellers/{seller_id}/messages (Enviar mensagem em conversa)GET /claims/search com type=claims (Reclamações abertas com motivo, etapa, deadline)POST /claims/{claim_id}/messages (Responder reclamação)POST /claims/{claim_id}/mediation (Escalar reclamação para mediação Mercado Livre)GET /claims/search com type=returns (Devoluções em processamento com status refunded/closed)
⚠️ AtençãoSincronização: perguntas/reclamações chegam a cada ~5 min via webhook ou manual (botão 'Atualizar agora'); se muita atividade, retardo é esperado — click sync forçado para obter dados frescos imediatamenteWhatsApp: notificações transacionais dependem de Blipei configurado no /perfil; killswitch global em /logs/.broadcast_paused pausa todas as notificações; opt-in por user (wa_ml_*_notif_enabled) desativa por tipo de eventoMediação ML: reclamação escalada passa por estágios (buyer_response → seller_response → mediation_accepted); prazo rigoroso — atraso na resposta desfavorece vendedor; sistema marca deadline em vermelho; responder rápido afeta reputação
10

Marketing (Mercado Ads)

Gerenciar campanhas de Product Ads (publicidade paga) no Mercado Livre para impulsionar vendas com controle de orçamento e métricas de performance (impressões, cliques, ROAS).

/central/marketing?tab=ads /central/marketing?tab=ads_pro /api/ml/ads/campaigns/api/ml/ads/metrics · clique pra abrir (já logado)
Tela real de Marketing (Mercado Ads) 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa Menu Lateral > Mercado Livre > Marketing (tela carrega Central de Marketing).
2Na aba 'Product Ads', visualiza campanhas ativas e pausadas com resumo de anúncios e orçamento/dia de cada uma.
3Clica em 'Nova Campanha', preenche nome e orçamento diário, e envia — a campanha aparece em tempo real na lista.
4Expande uma campanha e cola o ID do anúncio (MLB...) para adicionar itens — sistema sincroniza foto e título do ML automaticamente.
5Ativa/pausa campanhas ou anúncios individuais com clique, podendo também remover itens da campanha.
6Clica em 'Métricas (30d)' para visualizar impressões, cliques, custo total, CTR, vendas geradas e ROAS da campanha.
o sistema reage por baixo
⚙️ O sistema faz
Autentica
Valida token OAuth do vendedor com Mercado Livre e resolve advertiser_id da conta.
Sincroniza
Busca lista de campanhas da API v2 do ML (/marketplace/advertising/MLB/advertisers/{id}/product_ads/campaigns).
Renderiza
Carrega view Alpine.js com campanhas em JSON; vendedor vê resumo: status (ativo/pausado), quantidade de anúncios, orçamento/dia.
Cria
POST para ML com nome, orçamento diário, estratégia de lucratividade e ACOS alvo (15% padrão) — sistema retorna campaign_id.
Gerencia
Alterna status (pause/resume) e atualiza orçamento via PUT na API v2; remove anúncios via DELETE.
Coleta
Recupera métricas dos últimos 30 dias (impressões, cliques, custo, CTR, pedidos, ROAS) e calcula índices de eficiência.
Exporta
Gera CSV ou TXT com relação de campanhas, status e orçamento para análise offline.
🌐 Vai pro Mercado Livre / Pix
GET /users/me — resolve ID do vendedor autenticado.GET /advertising/advertisers?product_id=PADS — obtém advertiser_id para Product Ads.GET /marketplace/advertising/MLB/advertisers/{id}/product_ads/campaigns — lista campanhas com IDs, names, budgets, status.POST /marketplace/advertising/MLB/advertisers/{id}/product_ads/campaigns — cria nova campanha (name, budget, status, strategy, roas_target — UI ainda coleta ACOS, sistema converte pra ROAS = 100/ACOS antes de enviar; ML exige roas_target desde 08/12/2025).PUT /marketplace/advertising/MLB/advertisers/{id}/product_ads/campaigns/{campaign_id} — altera status (active/paused) e budget.GET /marketplace/advertising/MLB/advertisers/{id}/product_ads/campaigns/{id}/ads — lista anúncios dentro de uma campanha.POST /marketplace/advertising/MLB/advertisers/{id}/product_ads/campaigns/{id}/ads — adiciona item (MLB) à campanha.PUT /marketplace/advertising/MLB/advertisers/{id}/product_ads/campaigns/{id}/ads/{ad_id} — pausa/ativa um anúncio.GET /marketplace/advertising/MLB/advertisers/{id}/product_ads/campaigns/{id}/metrics?date_from=X&date_to=Y — métricas de campanha (impressões, cliques, custo, ROAS).
⚠️ AtençãoToken pode expirar: sistema tenta refresh automático com Mercado Livre; se falhar, vendedor vê erro e precisa reconectar conta em /lojas.ACOS alvo (15%) é default, mas deve ser ajustado conforme margem do produto — anúncios com ACOS alto (>25%) podem não ser rentáveis; sem custo cadastrado, sistema mostra 'Receita' não 'Lucro'. Internamente o ACOS é convertido pra ROAS (100/ACOS) antes de mandar pro ML — o campo acos_target foi descontinuado na criação em 24/02/2026.Adicionar mesmo MLB em duas campanhas simultâneas pode causar conflito de orçamento no ML; sistema não previne, vendedor deve atentar-se a overlaps.
11

Performance

Monitorar desempenho, compradores e funil de vendas em 5 abas analíticas integradas — do tráfego ao pagamento — com saúde das contas, visitas por anúncio e comparativos de período.

Tela real de Performance 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa o painel e clica em 'Performance' (grupo Mercado Livre)
2Aba Desempenho: vê KPIs por anúncio (visitas, conversão, faturamento, posição Buy Box nos últimos 30 dias) e identifica itens com baixa conversão
3Aba Compradores: vê distribuição entre clientes novos vs recorrentes, regiões, ticket médio e LTV — exporta base em CSV para campanhas
4Aba Funil: visualiza taxa de conversão em cada etapa (visita → pergunta → pedido → pagamento → entrega) com gargalos destacados em vermelho
5Aba Visitas: seleciona período (7, 15 ou 30 dias) e vê ranking dos anúncios mais visitados com gráfico de barras
6Aba Dashboard ML: vê resumo de todas as contas — total de anúncios, vendas dos últimos 30 dias e faturamento
7Acessa ferramentas relacionadas: Raio-X (saúde e score), Reputação (MercadoLíder, cancelamentos) ou Calculadora de margem
o sistema reage por baixo
⚙️ O sistema faz
fetch
Busca contas Mercado Livre vinculadas do vendedor na base de dados
validate
Verifica permissão do usuário para acessar módulo Performance (checa plan_guard)
load
Carrega dados agregados de visitas e anúncios: total da conta, total por item (via API ML /items_visits/time_window)
calculate
Processa score de saúde calculando 5 dimensões: anúncios ativos, estoque, tempo de resposta a perguntas, vendas e completude de perfil
rank
Ordena anúncios por visitas descendente e coleta metadados (título, thumbnail, preço)
render
Exibe KPIs (total visitas, média diária, melhor anúncio) e lista detalhada de cada anúncio com barra de proporção
🌐 Vai pro Mercado Livre / Pix
GET /users/{ml_user_id}/items_visits/time_window — total de visitas da conta num períodoGET /users/{ml_user_id}/items/search — lista anúncios ativos do vendedorGET /items/{item_id}/visits/time_window — visitas diárias de um anúncio específico (opcional)GET /items?ids=... — metadados em lote (título, foto, preço dos anúncios)
⚠️ AtençãoVisitas em fase 3 de desenvolvimento: dados podem estar incompletos, pois integração com API ML de visitas foi iniciada recentementeScore de saúde do Raio-X calcula offline baseado em dados locais (anúncios, estoque, perguntas) e pode divergir da realidade no ML se há desyncReputação ML descontinuou /reviews/pending em 2026-04-30 — retorna 404; dados de reputação vêm apenas de transações e nível do termômetro
12

Saúde da Loja

Monitorar a saúde operacional das contas Mercado Livre do vendedor visualizando reputação, histórico de 60 dias, taxas de cancelamento e atraso para identificar problemas e solicitar limpeza de vendas comprometidas.

/relatorio-saude /relatorio-saude/exportar.csv /relatorio-saude/exportar.txt /relatorio-saude/conta/{accountId}.json · clique pra abrir (já logado)
Tela real de Saúde da Loja 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa o painel e clica em 'Saúde da Loja' no menu do grupo 'Mercado Livre' (ícone: pacote)
2Visualiza um painel com 5 KPIs: contas críticas (vermelho), alertas (laranja), reconectadas (amarelo), pedidos atrasados e cancelados nos últimos 60 dias
3Consulta a tabela de lojas mostrando: vendedor, conta ML, reputação em termômetro de 5 barras coloridas, total de vendas, reclamações, atrasos, cancelados e taxa de problema (%)
4Filtra por criticidade (crítico, alerta, atenção, reconectar, OK) ou por vendedor para encontrar contas problemáticas
5Clica em uma linha da tabela para expandir detalhes da conta, visualizar histórico de problemas e, se necessário, solicitar remoção de venda comprometida (paga R$25 ao Rally)
6Exporta o relatório em CSV (Excel) ou TXT (legível por vendedor) para análise externa ou auditoria
o sistema reage por baixo
⚙️ O sistema faz
Recupera
Busca todas as contas Mercado Livre vinculadas (respeitando escopo: vendedor vê só suas, gerente vê sua carteira, admin vê todas)
Sincroniza
Consulta dados oficiais do Mercado Livre: reputação do vendedor (nível de termômetro), transações completadas, canceladas, reclamações (claims), atrasos (handling_time), pedidos dos últimos 60 dias via API /users/{mlUserId}
Valida
Verifica se os dados estão frescos (sync < 7 dias) ou desatualizados (token expirado ou sincronização não feita); marca como 'reconectar' se precisar renovar credenciais
Calcula
Computa taxa de problema: (reclamações + atrasos + cancelados) / total de pedidos, em porcentagem
Classifica
Atribui criticidade a cada conta: crítico (reputação vermelha ou >5% problemas), alerta (laranja ou 2-5%), atenção (amarela), reconectar (dados velhos), OK (verde e <2%)
Consolida
Agrupa métricas por conta ML: uma linha por conta, mesmo que vendedor tenha múltiplas. Computa KPIs globais (total de contas críticas, alertas, pedidos atrasados em toda base)
Filtra
Restringe visibilidade por multi-tenant: vendedor vê apenas seus dados; gerente vê bindings; admin vê tudo conforme permissão; remove contas sem reputação útil (termômetro vazio)
🌐 Vai pro Mercado Livre / Pix
Reputação do vendedor: GET /users/{mlUserId} para obter seller_reputation.metrics (claims, cancellations, delayed_handling_time) e nível de termômetro (level_id: red, orange, yellow, green)Programas Decola: GET /users/{mlUserId}/programs para verificar se o vendedor é elegível ao Programa Decola (acelerador para novos sellers)Sincronização de pedidos: recupera lista de vendas do Mercado Livre com status (paid, shipped, delivered, cancelled), datas e comissões armazenadas em cache local (não faz chamada direta aqui, usa dados pré-sincronizados)
⚠️ AtençãoContas sem reputação ML: lojas recém-criadas ou sem histórico não aparecem no relatório porque o termômetro está vazio — dados não são úteis para análise operacionalDesincronização: token expirado ou sincronização > 7 dias não mostra dados confiáveis; sistema avisa 'RECONECTAR' e tenta renovação automática, mas vendedor pode precisar reconectar manualmenteComissão e frete desconhecido: métricas de custo (frete, comissão real) podem ser estimadas em vez de oficiais se a sincronização não capturou todos os pedidos — recomenda-se vincular produtos aos custos unitários para precisão
13

Modo Férias

Pausar todos os anúncios ativos do vendedor no Mercado Livre com um clique, preservando configurações e permitindo reativação automática na data agendada.

/ferias /central/anuncios /dashboard · clique pra abrir (já logado)
Tela real de Modo Férias 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa o menu Mercado Livre → Modo Férias (ou /ferias direto) e visualiza o estado atual dos seus anúncios
2Define quando volta viajando (data e hora) ou deixa vazio para reativar manualmente — ambos opcionais
3Escreve mensagem automática personalizada para responder compradores durante o período (ex: 'Volto em 15/05')
4Clica 'Ativar Modo Férias' e confirma — todos os anúncios pausam em segundos no Mercado Livre
5Sistema reativa automaticamente na data escolhida (ou vendedor clica 'Reativar agora' em qualquer momento
6Vê resumo de quantos anúncios foram pausados e quantos voltaram ao ar
o sistema reage por baixo
⚙️ O sistema faz
Autentica
Verifica login do vendedor e carrega permissões de acesso ao painel
Carrega
Busca todos os anúncios ativos nas contas Mercado Livre conectadas do vendedor
Pausa
Envia requisição PUT a cada anúncio ativo para o Mercado Livre (status_change=paused) agrupando por conta para reusar tokens de acesso
Persiste
Salva estado atual da pausa (data, mensagem, quais anúncios foram pausados) em arquivo JSON local do usuário
Reativa
Ao clicar reativar ou na data agendada, envia PUT ao Mercado Livre (status_change=active) restaurando anúncios ao estado anterior
Agenda
Cron job a cada hora verifica se algum usuário tem data de retorno no passado e dispara reativação automática
Notifica
Retorna contagem de sucesso (X pausados, Y falharam) e exibe alerta visual no painel informando quantos anúncios foram reativados
🌐 Vai pro Mercado Livre / Pix
PUT /items/{item_id} com status_change=paused (pausar anúncio no Mercado Livre)PUT /items/{item_id} com status_change=active (reativar anúncio no Mercado Livre)GET /users/{user_id}/items (listar anúncios ativos da conta para identificar quais pausar)
⚠️ AtençãoTimeout ao pausar muitos anúncios: se vendedor tiver mais de 200 anúncios ativos, o limite de 180 segundos pode ser insuficiente — considerar fila assíncronaDesincronização silenciosa: anúncio pode ficar pausado no Rally mas ativo no ML se chamada à API falhar — histórico de erro é limitado a 10 itensReativação automática não dispara: se cron job não estiver rodando ou se vendedor tiver plano expirado, anúncios não reativam mesmo após data agendada
14

Transportadoras

Gerenciar parceiros transportadores para entregas Flex e despachos on-demand (Frete Center, Flex, Uber Direct).

Tela real de Transportadoras 📸 Tela real · clique pra ampliar
👤 Você faz e vê
11. Acesse o menu Mercado Livre > Transportadoras (grupo oculto, em evolução) ou direto em /painel/transportadoras.
22. Explore o Catálogo de transportadoras: veja regiões, preços e avaliações. Clique em uma oferta para mais detalhes.
33. Vincule uma transportadora: obtenha um código de 8 caracteres da transportadora parceira e cole no modal ou acesse /painel/transportadoras/vincular?code=XXXXX.
44. Gerencie prioridades: com múltiplas transportadoras vinculadas, o sistema pedirá que você escolha qual notificar para cada pedido em /painel/pedidos.
55. Acompanhe dispatches: veja status (pendente, aceito, em rota, entregue), preço cobrado e pagamentos PIX por transportadora em /painel/transportadoras/{id}/dispatches.
66. Declare lotes pro hub consignado: em /painel/transportadoras/lotes, crie lotes de anúncios com quantidade esperada. O operador do hub confirma recebimento no scanner.
o sistema reage por baixo
⚙️ O sistema faz
listar
Sistema busca todas as transportadoras vinculadas do vendedor (ativas), calcula KPIs: dispatches deste mês, quantidade em aberto e valor PIX a pagar.
validar
Sistema valida código de convite: checa cache local (CarrierInviteCode) ou consulta Frete.Center API para confirmar se código existe e não expirou (janela 72h).
vincular
Sistema cria vínculo (CarrierLink) entre vendedor e transportadora. Armazena PIX, chave tipo, e marcadores de hub consignado.
despachar
Quando vendedor marca pedido para dispatch, sistema consulta Frete.Center: cotação de frete, aceita/recusa, rastreia status em tempo real (pending → picked_up → in_transit → delivered).
conciliar
Sistema sincroniza descontos de frete ML com despachos Flex: se ML pagou frete direto, marca como pago; se Flex cobrou, gera débito PIX pendente.
receber
Operador do hub scaneia etiqueta de lote (ASN/WRO). Sistema registra recebimento e move estoque do nó origin_node_id para nó do hub automaticamente.
fechar
Sistema agrupa dispatches pagos por transportadora, gera comprovante PIX (upload para auditoria) e marca período como fechado.
🌐 Vai pro Mercado Livre / Pix
Frete Center API: valida código de convite (GET /carriers/invite-code/{code}).Frete Center API: busca transportadora por ID ou slug para catálogo público.Frete Center API: estima frete e cria dispatch (POST /dispatches), rastreia status.Mercado Livre API: verifica se pedido tem frete cobrado ou grátis (buyer paid frete), integra em reconciliação.Webhook Frete Center: recebe eventos de dispatch (status updates: picked_up, in_transit, delivered, refused) em tempo real.
⚠️ AtençãoMenu Transportadoras está oculto no painel (comentado em _sidebar_painel.php). Acessar direto em /painel/transportadoras exige plano 'frete_center_flex_dispatch' ativado.Com 2+ transportadoras vinculadas, cada pedido Flex novo exige escolha manual em /painel/pedidos. Auto-dispatch só funciona com 1 transportadora ativa; desvincule a segunda para retomar automático.Reconciliação: se ML descontou frete (buyer paid), mas Flex tambem cobrou, há risco de dupla cobrança. Sistema marca como 'pago' somente se ambas as fontes confirmam.
15

Fechamentos PIX

Vendedor visualiza fechamentos semanais consolidados de dispatches Flex por transportadora, localiza a chave PIX, efetua o pagamento direto e comprova o envio. (grupo oculto, em evolução — rotas existem mas o item de menu está comentado em _sidebar_painel.php; acesso direto em /painel/transportadoras/fechamentos.)

/transportadoras/fechamentos /transportadoras/fechamentos/{id}/comprovante/{filename} · clique pra abrir (já logado)
Tela real de Fechamentos PIX 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa o painel e clica em 'Fechamentos PIX' no menu Mercado Livre
2Vê lista de fechamentos por transportadora com período, número de dispatches e valor devido
3Localiza a chave PIX da transportadora (CPF/CNPJ/Telefone/Email) e realiza pagamento via seu banco
4Anexa o comprovante do PIX (foto ou PDF) no formulário de cada fechamento
5Aguarda confirmação da transportadora no painel Frete.Center; seu status muda para 'Pago'
o sistema reage por baixo
⚙️ O sistema faz
consolida
Sistema agrupa todos os dispatches Flex com pagamento aberto por transportadora e período ISO (semanal), executado diariamente via cron
calcula
Para cada grupo (transportadora + semana), soma a quantidade de deliveries e o valor total devido
persiste
Cria ou atualiza registro de FlexSettlement no JSON DB do vendedor com status inicial 'aberto'
exibe
Carrega lista de fechamentos da tela, mapeando PIX e dados da transportadora via CarrierLink
recebe
Valida upload de comprovante (PDF/PNG/JPG até 5MB) e armazena em storage/uploads/flex_receipts
marca
Registra URL do comprovante no FlexSettlement como 'parcial' até transportadora confirmar em Frete.Center
confirma
Transportadora marca como pago no seu painel externo (webhook ou integração); status muda para 'pago' com timestamp
🌐 Vai pro Mercado Livre / Pix
Nenhum — PIX é direto entre vendedor e transportadora; Rally não toca no dinheiro
⚠️ AtençãoFechamentos são calculados apenas se houver dispatches Flex com status payment.status='open'; sem Flex ativo, a tela não mostra nadaComprovante é opcional no fluxo atual (marcado como 'parcial'); apenas anexo não força status 'pago' — requer confirmação da transportadora no Frete.Center
Vitrine
16

Minha Vitrine

Vendedor navega e gerencia produtos de seus fornecedores drop vinculados para publicar no Mercado Livre com precificação automática.

painel.rallydevendas.com.br/fornecedorespainel.rallydevendas.com.br/fornecedores/{id}/vitrinedrop.rallydevendas.com.br/vitrine
Tela real de Minha Vitrine 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Vendedor acessa 'Fornecedores' no painel e vê lista dos seus fornecedores drop vinculados (com nome, logo e pontuação)
2Clica em um fornecedor para entrar em 'Minha Vitrine' e visualiza o catálogo completo (fotos e nome dos produtos; preço oculto até acionar detalhes)
3Usa filtros (busca, categorias, estoque) e visualiza dados de custo + margem + estoque para cada produto via modal de detalhe
4Define preferências globais de precificação: margem (%), tipo de anúncio (bronze/ouro/premium), frete grátis e promoção De/Por
5Seleciona produtos (checkbox em lote) e clica 'Anunciar', OU clica botão de publicação individual (1-clique) para enviar ao ML imediatamente
6Vê confirmação de sucesso com URL do anúncio e feedback de erros (categoria faltante, custo zero, etc.)
o sistema reage por baixo
⚙️ O sistema faz
buscar
Carrega lista de fornecedores vinculados ao vendedor com status, logotipos e pontuação
filtrar
Aplica categorias, busca por nome/SKU e filtra produtos ativos (sem pausados/inativos da vitrine)
carregar_detalhes
Busca dados completos do produto (fotos, EAN, dimensões, descrição) via endpoint /produto/{pid} ao abrir modal
ler_preferências
Recupera configurações salvas do vendedor (margem, tipo de anúncio, frete grátis, promoção) do banco de dados
calcular_preço
Aplica fórmula: Preço ML = Custo + Frete Médio, multiplicado por (1 + margem%), desconta taxa do Mercado Livre
publicar_ml
Envia anúncio ao Mercado Livre via API (fotos, dados, preço, atributos); retorna MLB (ID do item) e link permanente
persistir_prefs
Armazena preferências de margem, tipo de anúncio e modo de frete para reuso em próximos anúncios deste fornecedor
🌐 Vai pro Mercado Livre / Pix
POST para Mercado Livre: envia título, descrição, categoria, preço, foto (upload base64), atributos obrigatórios; retorna MLB + permalinkGET de dados de catálogo: valida NCM, consulta elegibilidade Flex, aplica regras de atributos obrigatórios do marketplace
⚠️ AtençãoContrato não aceito: vendedor vê modal de cláusulas antes de publicar; fluxo bloqueia até aceitar digitalmente (IP + timestamp auditado)Produto com dados incompletos (categoria não atribuída, custo zero, fotos ausentes): sistema exibe aviso de 'prontidão' (contador verde) e impede publicação até completarVinculação expirada ou plano sem permissão 'view_prices': vitrine pública oculta preços; painel do painel mostra erro 'Fornecedor não vinculado' se acessar rota diretamente
17

Vitrine Pública

Permitir que o vendedor configure e publique sua loja virtual pública com produtos curados, blog e domínio próprio, com visibilidade controlada por slug único e cidades.

/lojas (busca pública com filtros) /loja/{slug} (vitrine da loja)/loja/{slug}/p/{mlb} (página de produto)/loja/{slug}/blog (índice de posts)/loja/{slug}/blog/{post} (post individual)/perfil/loja (config no painel) /perfil/loja/produtos (curadoria ML + próprios) /perfil/loja/blog (gestão de posts) /api/v1/lojas/buscar (JSON público)/api/v1/lojas/{slug} (detalhe JSON) · clique pra abrir (já logado)
Tela real de Vitrine Pública 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Vendedor acessa Perfil > Vitrine Pública no painel e preenche nome da loja, descrição, logo, cover e cores
2Configura contato (WhatsApp/telefone), horário de funcionamento, localidade e redes sociais opcionais
3Faz upload de domínio próprio (A+CNAME) e aguarda verificação da Hostinger/Cloudflare
4Curada produtos: liga/desliga anúncios do Mercado Livre visíveis e adiciona produtos próprios com fotos
5Publica posts no blog interno (suporta SEO score, imagens, tags)
6Acessa /loja/{slug} ou domínio próprio pra visualizar a vitrine ao vivo
o sistema reage por baixo
⚙️ O sistema faz
Gerar
Sistema cria slug único automático ao salvar config da vitrine (baseado em shop_display_name ou nome do user)
Persistir
Salva todas as configurações (nome, descrição, logo, cover, cores, horas, categorias, contato) na tabela user com prefixo shop_*
Indexar
Carrega anúncios ativos do user (ML ou vitrine própria) filtrando por status e flag vitrine_visible
Buscar
API pública busca lojas por cidade, categoria ou termo, com facetas de filtro e pagination (24 itens/página)
Renderizar
Vitrine pública (VitrineController) renderiza HTML da loja com hero customizável, catálogo, blog, contactos e links legais
Verificar domínio
Sistema testa A+CNAME via Hostinger ou Cloudflare SaaS, aguarda SSL pronto, ativa quando verified_at não nulo
Gerar feed
Cria XML feed.xml para Google Shopping com todos os produtos visíveis (invalidado ao mudar config/produtos)
🌐 Vai pro Mercado Livre / Pix
GET /api/v2/items — busca anúncios ML do user para exibir na vitrine (paginado, com imagens)GET /api/v2/sites/MLB/reviews — busca avaliações do vendedor no Mercado Livre pra exibir na vitrine (reputação)GET /flex/v1/availability — verifica cobertura Flex por CEP pra avisar cliente sobre entrega express
⚠️ AtençãoDomínio próprio requer 2-3 dias após verificação da DNS para SSL ficar pronto (feedback claro no painel durante espera)Produtos ML continuam visíveis mesmo que desativados no Mercado Livre — flag vitrine_visible desacopla a curadoria da vitrine da vida real do anúncioFeed XML em cache pode ficar stale se vendedor edita produto rápido demais — cache invalidação ocorre ao salvar config
18

Produtos da Vitrine

O vendedor seleciona e gerencia produtos para sua vitrine pública, curando anúncios do Mercado Livre e adicionando produtos próprios, que são sincronizados em um feed Google Shopping para integração com Merchant Center.

/perfil/loja/produtos /loja/{slug}/feed.xml/loja/{slug} · clique pra abrir (já logado)
Tela real de Produtos da Vitrine 📸 Tela real · clique pra ampliar
👤 Você faz e vê
11. Acessa o painel → seção Vitrine → clica em 'Produtos da Vitrine'
22. Visualiza dois painéis: seus produtos próprios (criáveis via formulário) e anúncios ativos do Mercado Livre
33. Para cada anúncio ML, usa um toggle para ativar/desativar sua visibilidade na vitrine pública
44. Cria produtos próprios preenchendo nome, preço, descrição e fazendo upload de fotos
55. A vitrine pública em /loja/{slug} exibe os produtos selecionados em uma galeria
66. Periodicamente, o feed XML gerado em /loja/{slug}/feed.xml é buscado pelo Google Merchant Center para sincronizar produtos em Google Shopping
o sistema reage por baixo
⚙️ O sistema faz
carrega
Sistema obtém lista de anúncios ativos (ML) e produtos próprios (vitrine) do vendedor, respeitando a flag vitrine_visible de cada um
exibe
Renderiza dois blocos: produtos próprios com formulário de criação/edição, anúncios ML com toggle on/off para visibilidade
persiste
Salva alterações em tempo real: criação/edição/exclusão de produtos próprios, ativação/desativação de visibilidade de anúncios ML na tabela Announcements
constrói
Gera feed XML RSS 2.0 com namespace Google Shopping (LojaFeedService), mapeando cada produto para g:id, g:title, g:price, g:link (domínio próprio ou /loja/{slug}), g:image_link, g:condition, g:availability, g:brand, GTIN/MPN
cacheia
Armazena feed em storage/cache/shopping_feed_v2_*.xml com TTL 1h; Google refaz o fetch diariamente
publica
A vitrine pública em /loja/{slug} obtém os mesmos produtos via productsForLoja() e os exibe em galeria; /loja/{slug}/p/{mlb} fornece página de produto (landing para Merchant Center)
sincroniza
Envia ao Google Merchant Center via feed XML público em /loja/{slug}/feed.xml; Google Shopping aparece como outro canal de tráfego além de Mercado Livre
🌐 Vai pro Mercado Livre / Pix
GET /loja/{slug}/feed.xml → Google Merchant Center faz fetch diário do feed (autenticação via reivindicação de domínio)PUT para Mercado Livre API (legado) → quando produto é publicado no ML, Rally captura marketplace_item_id e preço para o feedGET em Google Shopping → listagem de produtos da vitrine após sincronização bem-sucedida do feed
⚠️ AtençãoDomínio próprio: se o vendedor reivindicar um domínio customizado no Merchant Center, os links de produto (g:link) devem ser do domínio verificado, não da Rally de Vendas — a tela não avisa visualmente dessa restriçãoRequisitos de dados: produto sem preço válido, foto ou permalink não entra no feed, causando silêncio sem aviso ao vendedorFoto formato: o feed usa ml_img() para converter imagens do ML para tamanho F (full), mas produtos próprios devem usar upload manual — sem validação de resolução mínima
19

Blog da Loja

Permitir que o vendedor crie e publique posts no blog da sua vitrine pública com otimização SEO e monetização via AdSense.

painel.rallydevendas.com.br/perfil/loja/blogpainel.rallydevendas.com.br/perfil/loja/blog/novopainel.rallydevendas.com.br/perfil/loja/blog/{id}/loja/{slug}/blog/loja/{slug}/blog/{post}
Tela real de Blog da Loja 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1O vendedor acessa o painel, clica em Vitrine > Blog da Loja e vê a lista de posts salvos (rascunhos e publicados)
2Clica em Novo Post ou Editar Post existente e preenche título, slug, capa, resumo, conteúdo (com editor visual WYSIWYG) e metadados SEO (descrição, palavra-chave, og:image, tags)
3Ao editar, vê em tempo real um score SEO (0-100) e um checklist com sugestões (título, densidade de palavras-chave, imagem, quantidade de subtítulos, etc)
4Faz upload de imagens inline dentro do editor (até 4MB, formatos JPG/PNG/WebP/GIF)
5Define status como Rascunho ou Publicado e salva; ao publicar, o post fica visível em /loja/{slug}/blog
6A vitrine pública do lojista mostra os posts publicados em grid (capa, título, resumo, data); clicando abre a página completa com conteúdo HTML, Open Graph, schema JSON-LD e anúncios Google AdSense
o sistema reage por baixo
⚙️ O sistema faz
Listar
Carrega todos os posts do vendedor (rascunhos e publicados) ordenados por data de publicação mais recente, com score SEO e tempo de leitura estimado em cache
Validar
Calcula score SEO (0-100) checando título, conteúdo (mínimo 500 palavras), densidade de keywords, meta description (50-160 chars), imagem de capa e estrutura de subtítulos (H2); retorna score + detalhes + sugestões
Guardar
Salva o post (create/update) em JSON per-user com slug automático, status, timestamps (created_at/published_at/updated_at) e metadados SEO (title, meta_description, focus_keyword, og_image, canonical_url, tags)
Subir
Move a imagem de capa/editor para /public/uploads/loja/{userId}/blog/ com nome aleatório (img_[hex].ext) e retorna URL relativa
Renderizar (público)
Mostra grid de posts publicados em /loja/{slug}/blog com card (capa lazy-loaded, título, resumo, data); ao clicar, renderiza /loja/{slug}/blog/{post} com conteúdo HTML, Open Graph (og:title, og:image, og:description), schema JSON-LD (BlogPosting), e include do ads.txt para AdSense
Indexar
Inclui na sitemap.xml de cada vitrine: /loja/{slug}/blog (changefreq=weekly) e cada post publicado com slug (changefreq=monthly) e lastmod do updated_at
Deletar
Remove o post da coleção JSON do usuário com confirmação CSRF
🌐 Vai pro Mercado Livre / Pix
POST /perfil/loja/blog/score: envia título, meta_description, focus_keyword, cover_url, conteúdo HTML e recebe score SEO (0-100) com checklist + sugestões em JSON
⚠️ AtençãoBlog fica oculto em /loja/{slug}/blog se shop_blog_enabled não estiver ativo no perfil do vendedor — validar que o usuário tem a flag habilitada antes de usar o editor (status 404 caso contrário)Score SEO usa throttle de 3s mínimo entre requisições para evitar WAF; se o vendedor digita rápido, pode parecer travado. Draft local salvo em localStorage (7 dias) pode conflitar se sessão expirouImagens inline no editor devem ser <4MB e formatos específicos (JPG/PNG/WebP/GIF); se usuário tentar .SVG ou HEIC, será rejeitado. URLs absolutas no canonical_url/og_image são obrigatórias para SEO funcionar (não URLs relativas)
Crescimento
20

Cursos

O vendedor acessa cursos de capacitação, assistindo videoaulas, lendo materiais e respondendo quiz para elevar seu potencial de vendas.

/cursos /cursos/{id}/cursos/{id}/{lesson_id}/acelera /acelera/dia/{n} · clique pra abrir (já logado)
Tela real de Cursos 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Clica em 'Cursos' no menu de Crescimento do painel e vê a lista de treinamentos disponíveis (cursos criados pelo admin ou seu gerente).
2Escolhe um curso e clica para entrar; o player mostra videoaulas, PDFs, textos e quiz organizados em módulos com barra de progresso visível.
3Assiste cada aula, marca como concluída e navega pela próxima; se a aula tiver quiz, responde as questões (precisa passar em 70% para seguir).
4Acompanha seu percentual de conclusão em tempo real no topo da tela (ex: 45% completo).
5Opcionalmente, entra no 'Acelera' para participar de um programa de 180 dias com missões diárias, checkin de presença e prêmios por sequência.
o sistema reage por baixo
⚙️ O sistema faz
Listar
Sistema busca cursos publicados visíveis para o vendedor (criados por admin ou seu gerente) e calcula o percentual de conclusão de cada um.
Renderizar
Exibe catálogo de cursos em cards com capa, título, resumo, e barra de progresso preenchida (ex: 45% — 7 de 15 aulas).
Carregar
Ao abrir um curso, carrega todos os módulos e aulas associados, e determina qual aula assistir (primeira não vista ou a última deixada aberta).
Reproduzir
Apresenta a aula no player (vídeo YouTube/Vimeo/nativo, PDF com anexos, ou texto HTML) com barra lateral mostrando todas as aulas do curso em ordem com status (concluída/pendente).
Marcar
Registra aula como concluída quando vendedor clica em 'Marcar como feito'; persiste no progresso e atualiza a porcentagem total do curso.
Avaliar
Se a aula for um quiz, processa respostas, calcula nota (pontos corretos ÷ total × 100) e bloqueia avanço se < 70% (permite tentar novamente).
Sincronizar
Atualiza progresso do curso em tempo real (barra, % concluído, status de cada aula) sem recarregar página; salva no banco JSON global.
⚠️ AtençãoQuiz com nota < 70% bloqueia a próxima aula até ser retentado; vendedor pode ficar desmotivado se pular muitas questões.Vídeos embarcados (YouTube, Vimeo) dependem de CDN externo; em conexões lentas, o player pode travá-lo.Progresso é local (por vendedor × curso); se o vendedor trocar de conta ou dispositivo, o histórico não sincroniza entre contas.
21

Check-in Diário

Vendedor registra venda do dia (faturamento + quantidade) e humor, recebendo feedback comparativo e mantendo streak de consistência diária.

/checkin /checkin/feito /checkin/historico · clique pra abrir (já logado)
Tela real de Check-in Diário 📸 Tela real · clique pra ampliar
👤 Você faz e vê
11. Acessa menu Crescimento → Check-in Diário (ou painel.rally.com.br/checkin).
22. Vê faturamento e pedidos de hoje dos marketplaces já preenchidos automaticamente; confirma ou corrige o valor de vendas fora dos marketplaces.
33. Seleciona seu humor (😡 😟 😐 🙂 😄) e escreve notas opcionais sobre o dia.
44. Clica 'Registrar check-in' e recebe página de sucesso com comparativas (vs ontem, vs média 7 dias, melhor dos 30 dias) + destaque motivacional.
55. Consulta histórico (últimos 60 dias) em /checkin/historico com tabela de data, faturamento, vendas, humor e notas.
66. Sistema mantém streak visível em ambas as telas (quantidade de dias seguidos com check-in registrado).
o sistema reage por baixo
⚙️ O sistema faz
auto_fill
Sistema busca Orders do vendedor da data e preenche automaticamente faturamento_auto e vendas_auto a partir de marketplaces conectados.
validar
Valida data (Y-m-d), sentimento (um de: muito_triste, triste, neutro, feliz, muito_feliz), e valores de faturamento/vendas (não negativos).
upsert
Grava ou atualiza check-in no JSON do usuário (idempotente por user_id + data). Separa auto/manual e armazena faturamento total = auto + manual.
calcular_streak
Computa sequência de dias consecutivos com check-in terminando em hoje/ontem (função pura, não persiste).
gerar_insight
Extrai comparativas: today (faturamento, vendas, sentimento), yesterday (delta %), avg_7d (delta %), best_30d, ticket_médio, e gera 1 frase de dopamina (recorde, streak, delta, sem venda, etc).
renderizar
Exibe form.php (com 4 cards: Vendas Online, Vendas Manuais, Total Ao Vivo, Humor+Notas), done.php (com hero + comparativas), ou history.php (tabela 60 dias).
integrar_gamif
Check-in contribui indiretamente ao sistema de pontos/níveis (SellerGamificationService); gamificação é cálculo em tempo real sobre ml_orders, não persistida no check-in.
🌐 Vai pro Mercado Livre / Pix
Nenhum. Check-in é ritual local: auto-fill lê Orders do banco JSON do user (not API). Streak e insights são cálculos puros sobre histórico local.
⚠️ Atenção1. Auto-fill depende de ml_orders.json sincronizado — se marketplace desconectado, faturamento_auto = 0 (vendedor deve preencher manual).2. Streak quebra se saltar 1 dia (hoje ou ontem deve ter check-in; 2+ dias sem = streak volta a 0).3. Check-in é idempotente por data (POST /checkin com mesma data atualiza o existente) — se vendedor refizer o dia, valores novos sobrescrevem (não há log de edições).
22

Lives & Eventos

Vendedor visualiza e participa de lives institucionais (mentorias ao vivo, eventos) agendadas pela plataforma com gravações disponíveis.

Tela real de Lives & Eventos 📸 Tela real · clique pra ampliar
👤 Você faz e vê
11. Clica no menu Crescimento > Lives & Eventos do painel do vendedor
22. Vê lista de eventos futuros com data, horário, descrição e duração em minutos
33. Clica no botão 'Entrar' para acessar o link da live (se disponível)
44. Acessa a live ao vivo ou assiste à gravação posterior (se existir)
55. (Admin) Agenda novo evento via formulário com título, descrição, data, hora, URL da live e audiência-alvo (todos / plano acelera / enrolled)
66. (Admin) Envia lembretes via WhatsApp para usuários notificáveis do evento
o sistema reage por baixo
⚙️ O sistema faz
Guard
Valida se vendedor tem permissão 'acelera.eventos' (plan guard) para acessar a tela
Query
Busca eventos institucionais futuros do banco JSON, filtrando por tenant e data agendada (scheduled_at >= agora)
Render
Exibe cartão para cada evento com data destaque, título, descrição, duração e botão 'Entrar' (se live_url existe)
Admin Create
Recebe dados do formulário, valida data/hora, cria novo evento no banco de dados JSON (InstitutionalEvent)
Admin Broadcast
Filtra audiência (todos / plano acelera / enrolled), valida quem já recebeu notificação (idempotência), dispara mensagem WhatsApp em lote
Track
Marca user_id como notificado no evento para evitar duplicação de lembrete
Public View
(Admin) Gera link público com token de 30 min para compartilhar live/tela campeão com token temporário
🌐 Vai pro Mercado Livre / Pix
Sem chamadas de API externa nesta tela — eventos e lives são gerenciados internamente via JSON Database e WhatsApp broadcast (serviço próprio da plataforma)
⚠️ AtençãoApenas usuários com permissão 'acelera.eventos' ativa veem a seção Lives & Eventos no menu (validação por PlanGuard)Links de live (live_url) são opcionais — se vazio, o botão 'Entrar' não aparece (sem erro, apenas oculto)Idempotência: mesmo após múltiplas chamadas de broadcast do mesmo evento, cada usuário recebe WhatsApp uma só vez (controle via notified_user_ids)
23

Grupos Telegram

Expor lista pública curada de 132 canais Telegram brasileiros (10k+ membros) em 15 nichos e capturar leads via bot deeplink para nurture.

/grupos /grupos/{niche} · clique pra abrir (já logado)
Tela real de Grupos Telegram 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Clica em 'Grupos Telegram' (item 132) no menu Crescimento do painel ou acessa rallydevendas.com.br/grupos
2Navega pelo hub público: escolhe um nicho (Promoções, Shopee, Ofertas, Cupons, Amazon, etc.)
3Na landing SEO de cada nicho, vê 3 grupos em acesso direto + lista de outros bloqueados
4Preenche email OU WhatsApp na caixa de desbloqueio
5Recebe link de bot (t.me/RallyBot?start=grupos_niche_code) que entrega a lista completa no Telegram
6Clica no link, o bot valida o código e envia todos os grupos do nicho como mensagem
o sistema reage por baixo
⚙️ O sistema faz
Valida
Confere se o niche existe, se email/WhatsApp é válido e aplica rate limit (3 unlocks/h por IP)
Gera
Cria registro de lead com unlock_code 8 chars alfanuméricos (sem 0/O/1/I para evitar confusão)
Monta
Constrói deeplink do RallyBot com parâmetros: grupo_niche_codigo para validação server-side
Armazena
Persiste lead em storage/json_db/group_unlock_leads.json com status=pending, email/WhatsApp e UTM
Retorna
Responde com JSON contendo bot_url para redirecionar o browser direto para o Telegram
Entrega
Bot recebe /start grupos_niche_code, valida unlock_code e envia lista de grupos como inline keyboard
Marca
Registra lead como status=delivered com tg_chat_id para cruzar em nurture sequence posterior
⚠️ AtençãoDeeplink do bot deve manter formato exato 'grupos_{niche}_{code}' — qualquer variação invalida a entregaOs 132 canais são carregados de telegram_groups.json (importado via TGStat); inatividade detectada por revalidação manual marca is_alive=falseEmail duplicado ou taxa esgotada (3 unlocks/hora) rejeitam unlock — usuário vê mensagem de erro no frontend
Extras
24

Ferramentas

Fornecer análise financeira e validação de anúncios para otimizar a rentabilidade das vendas no Mercado Livre.

Tela real de Ferramentas 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1O vendedor clica em 'Ferramentas' na seção Extras do painel
2Escolhe entre: Rentabilidade (simular lucro de produtos), Relatório (análise de vendas), Checar Fotos (validar imagens contra regras ML) ou integração com Mercado Pago
3Insere dados como preço de venda, custo do produto e outras variáveis de custo
4O sistema calcula margem líquida, impostos por regime tributário e lucro esperado
5Visualiza relatório de P&L com devoluções separadas, saldo recebido do MP e alertas de reconciliação
6Exporta dados em CSV, Excel ou PDF para análise externa
o sistema reage por baixo
⚙️ O sistema faz
Carregar
Busca anúncios e pedidos do usuário na base de dados local (JSON).
Calcular
Computa margem líquida usando preço bruto, comissão do ML (real ou estimada), frete, custo do produto, impostos e custos de publicidade.
Reconciliar
Compara valor esperado do ML com saldo efetivamente recebido no Mercado Pago, identifica retenções ou divergências.
Agrupar
Separa vendas válidas de devoluções, soma totalizações por período e regime tributário (CPF/MEI/Simples Nacional).
Validar
Avalia fotos de anúncios contra 20+ regras de qualidade do ML (dimensões, sobreposição de texto, marca d'água).
Exportar
Gera arquivo (CSV, XLSX ou PDF) com colunas de receita, custos, lucro e status para auditoria fiscal/contábil.
Conectar
Opcionalmente sincroniza com conta Mercado Pago (OAuth) para obter saldo oficial e status de liberação de valores.
🌐 Vai pro Mercado Livre / Pix
Valida foto contra regras JPEG/PNG (dimensões mín/máx, aspect ratio, texto em fundo, marca)Consulta saldo de conta no Mercado Pago (se conectada via OAuth)
⚠️ AtençãoComissão estimada quando falta sincronia real dos pedidos do ML — leitura desatualizada pode gerar margem incorretaCusto do produto vazio ou não sincronizado com anúncios — exibe alerta 'custo desconhecido' para que usuário vincule manualmentePeríodos de reconciliação MP podem levar 5-7 dias — nem todos os pedidos mostram saldo recebido imediatamente
25

Pesquisa de Mercado

Pesquisar concorrentes no Mercado Livre em tempo real, analisar preços/tendências e clonar anúncios vencedores sem sair do painel.

Tela real de Pesquisa de Mercado 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa Extras → Pesquisa de Mercado no menu lateral
2Digita uma palavra-chave (ex: airfryer) na aba Buscar no ML ou cola URL/HTML de página listada no Mercado Livre
3Seleciona a fonte: Rally Catalog (indexado, rápido) ou Mercado Livre direto (dados vivos)
4Vê resultados com preço, quantidade à venda, dias no ar e score Rally; filtra por preço e condição se quiser
5Clica em Clonar neste anúncio para copiar de um concorrente vencedor pra sua loja
6Usa abas adicionais: Analisar minha loja (comparação local vs pool), Tendências (Google Trends), Concorrência de Catálogo (repasse + buy-box)
o sistema reage por baixo
⚙️ O sistema faz
Busca
Consulta palavra-chave contra o Rally Catalog (pool indexado em 6h) ou chama API pública do Mercado Livre ao vivo; se API bloqueia (403), faz scraping HTML público como fallback.
Normaliza
Padroniza dados do item (id, título, preço, disponibilidade, vendas, foto, permalink) para exibição consistente.
Cache
Guarda resultado por 6 horas compartilhado entre todos os vendedores (dados ML são públicos); avita chamadas repetidas à API.
Analisa
Calcula estatísticas: mediana de preço, distribuição de concorrentes, histórico de vendas, oportunidades de posicionamento (tabela ao vivo vs histórico).
Renderiza abas
Monta visão em tabs: busca de palavras (Buscar no ML), self-analysis (Analisar minha loja), bypass via HTML (Colar HTML ML), Google Trends, e competição por catálogo (repasse + buy-box).
Gera insights
IA nativa sugere estratégia: gap de preço, sazonalidade, produto sem fotos (risco), itens com estoque zerado, pausa recomendada.
Clonar
Prepara fluxo integrado: clica Clonar → vai pra wizard de anúncio com dados do vencedor (título, preço, fotos) pré-preenchidos.
🌐 Vai pro Mercado Livre / Pix
GET /sites/MLB/search?q=X&limit=50 (API pública Mercado Livre — busca por palavra-chave)GET /items/{MLB_ID} (API pública ML — detalhes de um anúncio)POST /pesquisa-mercado/parse-html (servidor Rally faz parsing HTML quando usuário cola página ML direto)
⚠️ AtençãoMercado Livre pode bloquear a API pública (403) em certos IPs/períodos; nesse caso o sistema fallback para scraper HTML ou oferece aba Colar HTML como workaround.Rally Catalog tem TTL 6h — dados de busca não são 100% ao vivo, mas suficientemente frescos (mostrador de age: 'dados de 2h atrás' etc.).Extensão Chrome Rally permite coleta cooperativa, mas sem ela o pool cresce mais lentamente em categorias niche; aba Colar URL/HTML sempre funciona como bypass.
26

Checar Fotos

Validar fotos dos anúncios contra as regras do Mercado Livre (resolução, proporção, fundo branco) e permitir download com dica para melhorar via IA generativa.

Tela real de Checar Fotos 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa menu Extras > Checar Fotos no painel do vendedor
2Visualiza lista de anúncios próprios à esquerda, cada um com thumbnail e contagem de fotos
3Clica em um anúncio para ver análise automática: score (0-100) em cores + checks de quantidade/resolução/proporção/fundo/texto
4Visualiza galeria das fotos com preview em lightbox ao clicar, e botão Baixar para salvar cada imagem
5Copia o prompt de IA pré-gerado que indica como melhorar a foto em Gemini/ChatGPT (remover fundo, centralizar, etc)
6Baixa foto via proxy do Rally, abre Gemini/ChatGPT, cola prompt, anexa foto, gera versão melhorada e reuploada no ML
o sistema reage por baixo
⚙️ O sistema faz
Busca
Carrega lista de todos os anúncios do vendedor (até 400, filtrados por status ≠ deleted) com título, thumbnail e contagem de fotos
Analisa
Ao clicar em anúncio, faz fetch das imagens do CDN do ML e verifica: quantidade (0 a 12), resolução (px ≥500 ok, ≥1200 recomendado), proporção da capa (1:1 ideal), cor das bordas da capa (branco ≥240 RGB)
Pontura
Gera score 0-100 subtraindo penalidades por erros (−30) e alertas (−12), e lista até 7 checks com status ok/warn/error/info
Renderiza
Mostra painel direito com score colorido, checks em 2 colunas, galeria de fotos com números, lightbox, e prompt de IA copiável
Download
Quando vendedor clica 'Baixar', proxeia requisição para https://http2.mlstatic.com/* com curl, valida MIME type (jpg/png), e envia como attachment com nome foto_N.ext
Prompt
Monta texto instruindo especialista em ecommerce a melhorar a foto para regras do ML: fundo #FFFFFF, produto 80%, sem texto/preço/selo, 1:1, ≥1200px, iluminação uniforme
Cópia
Oferece botão 'Copiar prompt' que escreve no clipboard do vendedor via navigator.clipboard.writeText(), permitindo colar direto no chat da IA
🌐 Vai pro Mercado Livre / Pix
Valida características de imagem remota do ML CDN: detecta dimensões [w,h] via getimagesizefromstring() PHP, sensibilidade 4s por fotoDetecta cor de borda via GD Library imagecolorat() em 8 pontos (cantos + meios das bordas) para estimar fundo branco (≥240 R,G,B em ≥75% das amostras)Gera prompt textual (não API call) que o vendedor copia para Gemini ou ChatGPT passando a foto baixada, recebendo imagem melhorada manualmente
⚠️ AtençãoTimeout de 4s por imagem remota: se CDN do ML estiver lento ou foto removida, check vira 'info' (não pode certificar).Detecção de texto/selo/logo é apenas lembrete manual — o GD não identifica OCR, depende de revisão visual do vendedor.Download via proxy limita a URLs autorizadas (regex #^https://http2\.mlstatic\.com/[A-Za-z0-9/_\-\.%]+$#) — qualquer URL fora do padrão retorna erro 400.
27

Prompts de IA

Criar e reutilizar prompts de IA personalizados para gerar títulos, descrições, fichas técnicas, análises e respostas de anúncios.

/ia/prompts /api/ia/prompts/api/ia/prompts/salvar/api/ia/prompts/excluir/api/ia/prompts/default · clique pra abrir (já logado)
Tela real de Prompts de IA 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa Painel > Extras > Prompts de IA (menu na barra lateral)
2Visualiza lista de prompts criados com filtro por tipo (Título, Descrição, Ficha técnica, Análise, Resposta)
3Clica em 'Novo prompt' ou edita um existente em modal com nome, tipo e corpo do prompt
4Insere variáveis como {produto_nome}, {categoria}, {pergunta} usando botões de atalho
5Marca prompt como padrão do seu tipo (estrela) — usado automaticamente em gerações
6Salva e vê aparecer na lista; deleta prompts se não precisar mais
o sistema reage por baixo
⚙️ O sistema faz
Carrega
Busca todos os prompts do vendedor (tabela ai_prompts.json) com filtro por tipo e prompts já marcados como padrão
Valida
Verifica tipo válido (Título/Descrição/Ficha/Análise/Resposta), nome entre 1-60 caracteres e corpo entre 10-4000 caracteres
Armazena
Persiste prompt em JSON por usuário (users/{id}/ai_prompts.json) com timestamps created_at e updated_at
Marca padrão
Define prompt como padrão do seu tipo — desmarca outros prompts do mesmo tipo automaticamente
Descarta
Soft-deleta prompt (marca deleted_at) sem remover registro, para auditoria
Interpola
Substitui placeholders {var} no corpo do prompt pelos valores reais (produto_nome, categoria, etc.) na hora da geração
Resolve
Na hora de gerar IA, segue prioridade: prompt_id explícito > prompt padrão do tipo > default do sistema
🌐 Vai pro Mercado Livre / Pix
POST /api/ia/prompts/salvar: envia nome, tipo, corpo e marca padrão ao servidorGET /api/ia/prompts: recupera lista de prompts do usuário em JSONPOST /api/ia/prompts/excluir: marca prompt como deletadoPOST /api/ia/prompts/default: define prompt como padrão do seu tipo
⚠️ AtençãoPrompt precisa ter pelo menos 10 caracteres — validação no frontend e backendSó pode ter um prompt padrão por tipo — sistema desmarca os outros automaticamenteVariáveis {produto_nome}, {categoria} etc. não existem no prompt = são substituídas por string vazia na geração
28

Plugins & Extensão

Permitir vendedores gerenciar plugins de terceiros (incluindo extensão Chrome) e parceiros criar/manter integrações com acesso via Bearer token (em evolução).

Tela real de Plugins & Extensão 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Vendedor acessa o painel e clica em 'Plugins & Extras' no menu Extras do grupo lateral.
2Vê a galeria de plugins (gratuitos, premium e trial) com descrição, preço e status de instalação.
3Clica 'Instalar' em um plugin — o sistema valida plano, cobra se necessário, ativa e retorna com flash de sucesso.
4Pode desativar um plugin instalado clicando 'Desativar' (desativa sem cobrar novamente).
5Para extensão Chrome: abre o popup → aba 'Conta' → copia token Bearer via GET /ext/token (gerado da sessão autenticada do painel).
6Cola o token na extensão Chrome; ela passa a fazer requisições autenticadas (GET /ext/analise, /tracking, POST /ext/import-product, /ext/clone-announcement) com Authorization Bearer.
o sistema reage por baixo
⚙️ O sistema faz
Busca
Lê lista global de plugins aprovados (Plugin::all) e plugins instalados do usuário (PluginService::getUserPlugins).
Indexa
Monta dicionário installedIds[plugin_id] = status (active/inactive/revoked) para render rápido.
Valida
Na instalação: confere se plugin existe, está aprovado e se modelo de preço é compatível com plano do usuário (via PluginBillingService).
Cobra
Se plugin pago: PluginBillingService::chargeInstall incrementa wallet/créditos ou registra débito mensal.
Cria
Insere registro em user_plugins (JSON local) com id, plugin_id, status, pricing_model, paid_amount, installed_at.
Gera token
GET /ext/token cria ExtToken (Bearer) com TTL (expires_at), armazena hash em storage, devolve plain_token ao painel para vendedor copiar.
Retorna
Após ação (install/uninstall), redireciona com flash (sucesso/erro) e reload do marketplace.php.
⚠️ AtençãoTokens Bearer de extensão têm TTL fixo — extensão precisa renovar periodicamente via GET /ext/token; sem login válido no painel, devolve erro 401.Instalação de plugin pago requer saldo em carteira ou plano pago ativo; cobrança falha silenciosamente (erro em flash, sem exceção).Sem dados públicos no blueprint_flows.php — tela está em evolução e não tem fluxo mapeado oficialmente para usuários finais.
29

Blog Oficial

Acessar o blog público oficial do Rally de Vendas a partir do painel do vendedor para ler guias, tutoriais e estratégias de vendas.

Tela real de Blog Oficial 📸 Tela real · clique pra ampliar
👤 Você faz e vê
11. No painel do vendedor, clica no menu lateral no grupo 'Extras'
22. Clica no link 'Blog Oficial' (abre em nova aba, subdomain blog.rallydevendas.com.br)
33. Vê a listagem de artigos em cards com imagem, título, categoria, tempo de leitura e data
44. Busca por termo digitando na caixa de pesquisa OU filtra por categoria (Guia, Estratégia, Ferramenta, etc)
55. Clica em um card para ler o artigo completo com índice, autor, comentários e artigos relacionados
66. Rolando a página, vê progresso de leitura, opções de compartilhamento e captura de lead (WhatsApp)
o sistema reage por baixo
⚙️ O sistema faz
carrega
BlogIndexService lê índice leve (~500KB) com posts publicados, ignora o arquivo pesado blog_posts.json (13MB) na memória
renderiza
Lista até 12 posts por página em grid com imagem, categoria colorida, tempo estimado de leitura e data. Suporta busca por termo no título/keyword/descrição e filtragem por categoria
navega
Usuários logados veem blog integrado ao painel (com sidebar). Públicos veem versão standalone com header/footer público
exibe post
BlogController::post() busca artigo por slug, valida existência (404 se não encontrado), registra visualização via BlogTrackingTrait
enriquece
Adiciona metadados SEO (JSON-LD Article + BreadcrumbList + FAQ schema), Open Graph, Twitter Card, RSS link. Integra Google AdSense (ca-pub-2442955258067136)
captura
POST /api/lead coleta WhatsApp + nome do leitor e envia checklist automaticamente via BlogLeadService. Salva em blog_leads.json
tracked
Google Analytics 4 (GA4) e Microsoft Clarity rastreiam visualizações. Pixel de tracking invisível registra evento de view. Meta Pixel (881126080985979) dispara PageView.
🌐 Vai pro Mercado Livre / Pix
POST /blog/api/lead — envia WhatsApp do leitor para captura de contato (resposta JSON {success: true/false})
⚠️ AtençãoBlog posts.json tem 13MB — BlogController DEVE usar BlogIndexService (índice de 500KB), nunca carregar o arquivo inteiro na RAMAdSense e Analytics disparam píxeis de rastreamento — verificar CSP nonce e GDPR ao integrar novo tracking terceiroURLs canônicas e JSON-LD são críticas para SEO — manter consistência entre og:url, canonical e sitemap.xml gerado em tempo real
Parceiros
30

Afiliados

O vendedor gerencia seu programa de afiliados MLM de 2 níveis para ganhar comissões de 25%/5% sobre novos clientes indicados.

/afiliados /afiliados/apply · clique pra abrir (já logado)
Tela real de Afiliados 📸 Tela real · clique pra ampliar
👤 Você faz e vê
11. Clica em 'Afiliados' no menu (grupo Parceiros) do painel do vendedor
22. Sistema exibe painel com status: inativo ou ativo com rede de indicações (L1 e L2)
33. Se inativo, clica em 'Quero ser afiliado' para ativar (aprovação automática para planos pagos, pendente para free)
44. Copia seu link de indicação único (com código referral) ou compartilha direto via WhatsApp
55. Visualiza a rede de indicados (Nível 1 diretos + Nível 2 indiretos) com comissões acumuladas
66. Acompanha ganhos pendentes, pagos e taxa de conversão dos cliques (últimos 30 dias)
o sistema reage por baixo
⚙️ O sistema faz
load
Sistema lê status do vendedor em users.json (affiliate_status: active/pending/blocked) e carrega árvore de indicados (L1 diretos + L2 indiretos via L1)
apply
Ao clicar 'Quero ser afiliado', gera código referral único, ativa imediatamente (auto_approved=true para planos pagos), cria link global de indicação no AffiliateLink
calc
Calcula comissões L1 (25% do plano = R$100-500/mês) e L2 (5% do plano = R$20-100/mês) para cada indicado com first_paid_at há ≥90 dias (carência contra churn)
rank
Atribui tier ao afiliado (Bronze 1-2, Prata 3-9, Ouro 10-24, Diamante 25+ indicados ativos) e bônus mensal por tier (0 a R$400/mês)
track
Registra clicks (utm_source=affiliate) e conversões (first_sale + recurring) em AffiliateConversion pending até elegibilidade (90d) ser atingida
payout
Cron mensal credita Wallet do afiliado com conversões elegíveis, respeitando cap individual (R$1.000/mês) e cap global (15% MRR da empresa)
⚠️ Atenção⚠️ Carência 90 dias: comissão só crédita se o indicado pagou há ≥90 dias (previne fraude e churn rápido)⚠️ Limite mensal R$1.000 por afiliado + 15% MRR global: payout para automaticamente se atingir cap (configurável em affiliate_config.json)⚠️ Aprovação automática mudou em 2026-05-21: agora TODOS os planos (free + paid) são auto-aprovados; admin apenas bloqueia suspeitos
31

Campanhas

O vendedor acessa seu painel de programa de afiliados para criar links de campanha com rastreamento UTM, acompanhar comissões de indicações e visualizar ofertas especiais de aquecimento de vendas.

mkt.rallydevendas.com.br/painel/indicacao?tab=afiliado (dashboard afiliado)mkt.rallydevendas.com.br/painel/afiliado/links (lista e cria campanhas)mkt.rallydevendas.com.br/painel/afiliado/relatorios (extrato de comissões)painel.rallydevendas.com.br/esquenta (ofertas aquecimento)mkt.rallydevendas.com.br/afiliados (landing pública)mkt.rallydevendas.com.br/ranking (ranking de afiliados)
Tela real de Campanhas 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Na seção 'Parceiros' do menu, clica em 'Campanhas' para ir ao painel de afiliado
2Visualiza seu link principal (sem parâmetros) e cria novos links com nome, URL de destino e tags UTM (source, medium, campaign) para rastrear cada canal
3Copia o link gerado e compartilha via WhatsApp, email ou Instagram para trazer pessoas pro Rally
4Acompanha em 'Extrato' quantas vendas geraram cada campanha e sua comissão acumulada
5Acessa 'Esquenta' para ver ofertas especiais que pode ativar (-5% em anúncios por 14 dias) para impulsionar vendas
o sistema reage por baixo
⚙️ O sistema faz
autenticação
Valida que o usuário está logado e tem acesso ao programa de afiliados (status=active no banco)
carrega
Busca link principal (kind=global) e todas as campanhas do vendedor (kind!=global) no banco de dados
renderiza
Exibe modal para criar nova campanha com campos: nome, URL destino, UTM source/medium/campaign
cria
Persiste novo link no banco com código único, associado ao user_id do vendedor
copia
Gera URL completa (domínio afiliado + código + parâmetros UTM) em campo readonly + botão copiar
rastreia
Sistema de click tracking registra cada clique no link para calcular conversões e comissões no mês
🌐 Vai pro Mercado Livre / Pix
GET /api/ml/campanhas - Listar campanhas disponíveis no Mercado Livre (DEAL, Lightning, etc) que o vendedor pode participarPOST /api/ml/campanhas/participar - Adicionar produto a uma promoção ML com preço específicoPOST /api/ml/campanhas/sair - Remover produto de uma campanha ML
⚠️ AtençãoLinks criados pelo afiliado são para rastrear o próprio tráfego (ex: Instagram) - não confundir com campanhas de promoção do Mercado Livre (Ofertas do Dia, Lightning, etc)Sorteio mensal (R$500 para afiliado com mais conversões) é automático (roda 1º do mês, sem ação do usuário)Se o vendedor estiver bloqueado ou com status cancelado, não consegue acessar painel nem criar campanhas
32

Extrato

Permitir que o vendedor afiliado acompanhe todas as comissões geradas (pendentes e pagas) e as transferências de créditos para a Wallet.

Tela real de Extrato 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Clica em Parceiros → Extrato no menu do painel (grupo 'Parceiros')
2Vê o saldo de comissões em 4 cartões: Pendente (aguardando 90 dias), Pago (já na carteira), Lifetime (total acumulado) e MRR (recorrente do mês)
3Filtra conversões por status (Todas, Pendentes, Pagas, Canceladas) e vê a tabela com data, tipo (1ª venda ou recorrente), nível (L1 ou L2), valor, origem, status e data de pagamento
4Volta à tela anterior para gerenciar links de campanha (/painel/afiliado/links)
o sistema reage por baixo
⚙️ O sistema faz
Autoriza
Verifica autenticação e permissão de acesso ao programa de afiliados (roles: admin, gerente, drop, cliente)
Valida
Confirma que o usuário está ativo no programa de afiliados; se não, bloqueia acesso
Carrega
Busca todas as conversões (AffiliateConversion) do usuário ordenadas por data decrescente
Calcula
Agrega estatísticas em centavos: soma de pending, paid, lifetime e MRR (recorrente do mês corrente)
Renderiza
Exibe KPIs (cartões de saldo) e tabela filtrável com todos os registros de comissão com status visual
Formata
Converte centavos em BRL (ex: 5000 centavos = R$ 50,00) e exibe datas em ISO 8601 para legibilidade
⚠️ AtençãoComissões pendentes só liberam após 90 dias do primeiro pagamento do indicado; vendedor novo pode ficar frustrado vendo saldo travadoSe o indicado (L1) cancelar o plano retroativamente ou sofrer chargeback, a comissão é cancelada/revertida automaticamente (clawback)Nível 2 (L2) só funciona se o referidor (L1) foi indicado por outro afiliado ativo; indicações orgânicas não geram cadeia L2
Config & Conta
33

Configurações

O vendedor acessa suas configurações de perfil pessoal, dados fiscais, nacionalidade, chaves de IA próprias (BYOK), verifica seu WhatsApp e escolhe COMO recebe cada tipo de notificação no WhatsApp.

Tela real de Configurações 📸 Tela real · clique pra ampliar
👤 Você faz e vê
11. Clica em 'Config & Conta' no menu lateral (ícone de engrenagem)
22. Vê as abas 'Meu Perfil', 'Carteira Digital', 'Contas ML' e 'Fornecedores'
33. Na aba 'Meu Perfil', acessa seu avatar, nome, email e plano; clica em 'Editar Perfil' ou 'Alterar Senha'
44. Em '/perfil', preenche dados pessoais: nome, email, WhatsApp, nacionalidade, país de operação, CPF/CNPJ, PIX
55. Verifica email/WhatsApp clicando no botão 'Verificar' (recebe código por email ou WhatsApp)
66. Na aba 'Integrações & IA', ativa suas próprias chaves de Claude, Gemini ou OpenAI; testa cada uma antes de salvar
77. Na aba 'Notificações', escolhe por tipo (Vendas / Perguntas & mensagens / Reclamações & devoluções) COMO receber no WhatsApp: imediato (1 mensagem por evento), resumo diário às 09:30, ou desligado
o sistema reage por baixo
⚙️ O sistema faz
carrega
Busca dados do usuário no banco: perfil, plano, contas Mercado Livre, preferências
renderiza
Exibe abas (Meu Perfil, Carteira, Contas ML, Fornecedores) conforme permissões do usuário
valida
Verifica email/nome (min 3 caracteres), email único se mudar, WhatsApp com +55, nacionalidade contra lista de países
criptografa
Protege chaves de IA (Claude/Gemini/OpenAI) antes de salvar no banco
envia
Dispara código de verificação por email (SMTP) ou WhatsApp (API Blipei)
testa
Faz chamada real à API do provedor de IA para confirmar chave válida
exporta
Gera JSON com todos os dados do usuário (LGPD Art. 18 V: dados pessoais, anúncios, pedidos, histórico de IA)
notifica
Salva o modo de notificação por tipo. No imediato dispara 1 WhatsApp por evento; no diário enfileira o evento no mesmo resumo das 09:30 que já vai pra gerente/fornecedor/admin; desligado não envia. Default: imediato (zero mudança pra quem já usa).
🌐 Vai pro Mercado Livre / Pix
Envia SMS/WhatsApp via Blipei (serviço terceirizado de mensageria) para verificação de númeroFaz teste de autenticação contra API Claude (Anthropic), Gemini (Google AI Studio) ou OpenAI (se chaves BYOK forem preenchidas)
⚠️ AtençãoDocumento fiscal (CPF/CNPJ) é opcional, mas avisa se o formato não bater com o país de operação selecionadoSe mudar nacionalidade de BR para outro país, PIX é limpo automaticamente (PIX só funciona no Brasil)Chaves de IA não são salvas em pleno texto—são criptografadas e o sistema mostra apenas uma máscara (ex: 'sk-ant-***')
34

Meu Plano

Vendedor visualiza e gerencia seu plano atual, vê período de trial, compara planos (free vs paid/managed) e realiza upgrade com checkout flexível via Mercado Pago (cartão, PIX ou boleto).

Tela real de Meu Plano 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Clica no ícone de coroa no menu lateral (seção 'Gestão') ou no drawer completo para acessar 'Meu Plano'
2Vê seu status atual: trial ativo com dias restantes, trial expirado, ou plano ativo (free/paid/managed)
3Compara lado a lado os planos: free (ilimitado ML + anúncios) vs paid (R$ 29,90/mês + R$ 1,00 por venda com vitrine, blog, shopping)
4Interage com simulador de custo: arrasta barra para estimar quantas vendas faria no mês e vê custo total amortizado por pedido
5Escolhe método de pagamento (Cartão = assinatura automática via Mercado Pago ou PIX/Boleto = pagamento único mensal)
6Clica 'Ativar Plano' ou 'Gerar Código PIX' e é levado ao checkout do Mercado Pago
o sistema reage por baixo
⚙️ O sistema faz
Carrega
Busca plano atual do usuário (free/paid/managed), verifica status do trial (ativo/expirado/sem trial), calcula dias restantes se ativo, obtém todos os planos ativos do sistema
Compõe
Renderiza estado visual do trial/plano em banner destacado (aviso, relojoura de contagem regressiva ou cadeado de expiração)
Exibe
Mostra dois cards comparativos de plano gratuito vs plano pago com listas de features verificáveis (perguntas, mensagens, raio-X, vitrine, blog, suporte)
Calcula
Busca histórico de vendas no mês atual, apresenta simulador que recalcula taxa mensal + taxa por venda conforme usuário arrasta slider
Valida
Verifica se Mercado Pago está configurado (MP_ACCESS_TOKEN em .env), se não nega acesso com mensagem de erro
Direciona
POST /planos/checkout recebe choice de plan_id, period, payment_method; cria preference (método flex = PIX/boleto com link avulso; card = preapproval com assinatura automática) e redireciona ao initPoint do MP
Registra
Salva pref_id e billing_status (flex_pending ou preapproval_pending) para webhook processar confirmação; após sucesso, plan muda de free para paid, TrialGuardMiddleware libera acesso pleno
🌐 Vai pro Mercado Livre / Pix
Mercado Pago: createPreapproval (cartão com renovação automática) envia dados de cobrança recorrente; createPreference (PIX/boleto) gera link de checkout avulso; webhook valida approval e credita wallet + muda plan do usuário
⚠️ AtençãoTrial expirado bloqueia acesso via TrialGuardMiddleware — whitelist inclui /planos para que usuário possa ver opções de upgrade; se não chegar aqui, permanece bloqueado em redirect loopBUG-PLAN-CUSTOM-PRICE-001: administrador pode sobrescrever custom_per_order_price do usuário no admin; view respeita override individual, não preço defaultRDV-MP-FLEX-001: dois fluxos paralelos — 'card' usa Preapproval (debit automático, só cartão/conta MP) vs 'flex' usa Preference avulsa (aceita PIX, boleto, cartão mas sem renovação automática); vendedor escolhe ambos a cada mês
Loja com checkout
35

Ativar a Loja com checkout

Transformar a vitrine (que era só catálogo) numa loja que vende direto: o cliente compra, paga e recebe, tudo pelo Rally.

/perfil/loja · clique pra abrir (já logado)
Tela real de Ativar a Loja com checkout 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Em Vitrine pública, as configurações ficam em 3 abas: Loja, Vender e Avançado.
2Na aba Vender, liga "Habilitar venda direta" — aí aparece o botão Comprar na vitrine.
3Escolhe o que a vitrine mostra: produtos próprios + Mercado Livre, só próprios ou só ML.
4Define como recebe: chave PIX (gera QR no checkout), Mercado Pago (conecta a conta dele) e/ou pagamento na entrega.
5Informa o CEP de origem (digite o CEP que rua/cidade preenchem sozinho via ViaCEP — você só põe o número; se não achar, preenche à mão) e liga os métodos de frete (Correios, Uber, Flex, retirada). Tudo isso só vale se você vende produto próprio; quem mostra só Mercado Livre não precisa configurar pagamento/frete.
o sistema reage por baixo
⚙️ O sistema faz
Salva
Grava a config da loja (pagamento, frete, origem) no perfil do vendedor.
Gateia
O botão Comprar só aparece com a venda direta ligada; anúncio de ML sempre vai pro Mercado Livre.
Conecta
Mercado Pago via OAuth do próprio vendedor — o dinheiro cai na conta dele, nunca na do Rally.
⚠️ AtençãoLogin Google no checkout exige a origem do domínio autorizada no Google Cloud Console.Login Mercado Livre do comprador exige registrar a redirect_uri /checkout/ml/callback no app ML.
36

Comprar na vitrine (checkout rápido)

O comprador fecha o pedido em 1-2 cliques, mobile-first, com o endereço já preenchido.

/loja/{slug}/loja/{slug}/checkout
Tela real de Comprar na vitrine (checkout rápido) 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Na página do produto, clica em "Comprar agora".
2Se identifica em destaque com Mercado Livre (puxa nome + e-mail + telefone + endereço) — ou Google (1 toque) ou como visitante.
3Digita só o CEP: o endereço é preenchido sozinho (ViaCEP) e o frete é cotado na hora.
4Escolhe a entrega, escolhe o pagamento (PIX, Mercado Pago ou na entrega) e finaliza.
5Cai na página do pedido com o status e as instruções de pagamento.
o sistema reage por baixo
⚙️ O sistema faz
Identidade
Login ML/Google/visitante cai no CRM de clientes (Buyer) — recompra fica em 1 clique.
Endereço
CEP via ViaCEP + cotação de frete em tempo real pelo gateway (Correios/Uber/Flex/retirada).
Lead
Captura o lead (nome+WhatsApp) já no passo 1 — base da recuperação de carrinho.
Pedido
Recalcula tudo no servidor (nunca confia no preço do cliente) e cria o pedido da loja.
🌐 Vai pro Mercado Livre / Pix
OAuth comprador: troca o code, lê /users/me + /users/{id}/addresses pra pré-preencher o endereço (não cria conta nem marketplace_account).
⚠️ AtençãoProduto de ML não entra no carrinho — só produto próprio é vendido pelo checkout (ML é fulfilled pelo Mercado Livre).Google One Tap só renderiza em domínio autorizado; em domínio próprio do lojista cai pra ML/visitante.
37

Pagamento da loja (PIX, Mercado Pago, na entrega)

Receber o pagamento do jeito que o vendedor escolheu — direto na conta dele.

/loja/{slug}/pedido/{token}
Tela real de Pagamento da loja (PIX, Mercado Pago, na entrega) 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1PIX: a página do pedido mostra QR Code + copia-e-cola com o valor já preenchido; o comprador paga e manda o comprovante.
2Mercado Pago: o comprador é levado ao checkout do MP do vendedor (PIX, cartão, boleto — com o parcelamento que ele liberou).
3Na entrega: o comprador combina e paga ao receber.
o sistema reage por baixo
⚙️ O sistema faz
PIX
Gera o BR Code (EMV + CRC16) sem API de banco — a confirmação é o vendedor que dá (comprovante).
Mercado Pago
Cria a preference na conta MP do vendedor (token dele) com as opções configuradas (parcelas/cartão/boleto/PIX).
Confirma
O webhook do MP confirma o pagamento automático (busca no token do vendedor) e marca o pedido pago.
🌐 Vai pro Mercado Livre / Pix
Mercado Pago: createPreference na conta do vendedor (collector próprio) + webhook /webhooks/pagamento/mercadopago?store_seller=X pra confirmar e dar baixa.
⚠️ AtençãoPIX da chave própria não confirma sozinho (o banco não avisa o Rally) — pra automático, use o Mercado Pago PIX.Mercado Pago só aparece no checkout se o vendedor conectou a conta dele (MP Connect).
38

Frete + Etiqueta da loja

Cotar o frete certo pelo CEP e despachar com etiqueta — mesmo quando a transportadora não fornece uma.

/loja/{slug}/checkout/loja/pedidos · clique pra abrir (já logado)
Tela real de Frete + Etiqueta da loja 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1No checkout, o comprador vê as opções de entrega válidas pro CEP dele (com preço e prazo).
2Depois de pago, o vendedor abre o pedido em /loja/pedidos e clica em Etiqueta.
3Imprime a etiqueta (remetente + destinatário + QR) e cola no pacote.
o sistema reage por baixo
⚙️ O sistema faz
Cota
Gateway de frete: Frete.center (transportadora vinculada), Uber Direct (≤5km, same-day), Flex (mesmo dia em SP), retirada, ou estimativa.
Regras
Uber só aparece se o destino está na área (~5km); Flex só na região de SP e com produto elegível (peso/dimensão).
Etiqueta
Loja/Uber/Flex não têm etiqueta de transportadora → o Rally gera a própria (imprimível, com QR). Correios/transportadora trazem a oficial.
⚠️ AtençãoFrete grátis acima de um valor mínimo zera a opção padrão (transportadora).Sem CEP de origem configurado, Uber e a cotação de transportadora não rodam.
39

Gerenciar pedidos + recuperar carrinho

O vendedor acompanha as vendas, confirma pagamento, despacha e recupera quem deixou o carrinho.

/loja/pedidos /loja/leads · clique pra abrir (já logado)
Tela real de Gerenciar pedidos + recuperar carrinho 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Em /loja/pedidos vê os pedidos por status, confirma o PIX manual, marca como enviado e abre a etiqueta.
2É avisado na hora de cada nova venda (WhatsApp → Telegram → e-mail); o comprador recebe e-mail em "pago" e "enviado".
3Em /loja/leads vê o Kanban de carrinhos abandonados e exporta o CSV pra recuperar do jeito dele.
o sistema reage por baixo
⚙️ O sistema faz
Confirma
PIX manual / na entrega vira "pago" com um clique; Mercado Pago confirma sozinho pelo webhook.
Avisa
Vendedor via NotifyDispatchService (cascata); comprador via e-mail transacional (zero risco de ban WhatsApp).
Recupera
O lead+carrinho fica no CRM do vendedor; a recuperação é canal DELE (Blipei/SMTP) ou export manual — o Rally não dispara nada.
⚠️ AtençãoA recuperação por WhatsApp/e-mail é responsabilidade do vendedor (integração dele) — evita risco de ban da conta do Rally.
40

Avaliações + Produto de fornecedor (drop) na loja

Ter prova social na página do produto e vender produto de fornecedor pela loja própria.

/loja/avaliacoes /fornecedores/{id}/vitrine · clique pra abrir (já logado)
Tela real de Avaliações + Produto de fornecedor (drop) na loja 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Avaliações: o comprador avalia o produto (estrelas + texto) e aparece na hora; o vendedor esconde as ruins em /loja/avaliacoes.
2Pode importar as avaliações reais do mesmo produto no Mercado Livre pra ter prova social desde o dia 1.
3Drop na loja: no catálogo do fornecedor, clica "Adicionar à minha loja" — vira produto próprio (personalizável) com vínculo oculto ao fornecedor.
4Quando esse produto vende na loja, o fornecedor é acionado pra despachar e o vendedor paga o custo (fluxo drop que já existe).
o sistema reage por baixo
⚙️ O sistema faz
Avalia
Avaliações entram visíveis (auto-aprova); o vendedor modera escondendo as problemáticas.
Importa
Puxa as reviews do MLB pelo token do vendedor (/reviews/item/{MLB}), com dedup.
Drop
Venda paga de produto com drop_origin cria um pedido drop → o fornecedor despacha e o vendedor paga (margem = preço da loja − custo).
🌐 Vai pro Mercado Livre / Pix
Avaliações: GET /reviews/item/{MLB} (token do vendedor) pra importar a prova social do anúncio do mesmo produto.
⚠️ AtençãoImportar avaliações exige uma conta Mercado Livre conectada e o MLB do mesmo produto.O pedido drop entra na pipeline de /fornecedores — o vendedor paga o fornecedor (PIX/wallet) e ele despacha.
Mercado Livre
41

Monitor de Catálogo + Precificação IA

Monitorar a posição no Buy Box do Mercado Livre, ajustar preços manualmente ou via sugestão de IA (BYOK) e ativar auto-repricing automático a cada ~55 min — com piso de preço, cooldown e histórico de mudanças.

/central/anuncios?tab=catalogo /api/ml/catalog/monitor/status/api/ml/catalog/monitor/reprice-now/api/ml/catalog/monitor/ai-suggest · clique pra abrir (já logado)
Tela real de Monitor de Catálogo + Precificação IA 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa Central de Anúncios → aba Catálogo e vê anúncios em catálogo com status do Buy Box (vencedor/concorrente/perdendo) e preço vencedor atual
2Clica em "Aplicar agora" para ajustar o preço ao valor vencedor do Buy Box com 1 clique
3Clica no botão IA (ícone robô) para obter sugestão automática via BYOK: a IA analisa concorrentes, preço atual e piso e recomenda baixar | manter | subir com justificativa
4Ativa o auto-reprice nas configurações do catálogo: define piso de preço mínimo (ex: R$ 89,90) e se quer ajuste automático a cada ciclo de monitoramento
5Acompanha histórico de mudanças de preço por anúncio (data, preço anterior, preço novo, motivo: auto/manual/IA)
6Recebe alerta via Telegram quando o auto-reprice não consegue vencer o Buy Box mesmo no preço mínimo
o sistema reage por baixo
⚙️ O sistema faz
Monitor
Cron a cada ~55 min executa CatalogMonitorService::runAll(): para cada anúncio em catálogo, consulta ML Buy Box Status e dados de concorrência
Compara
Calcula se preço atual está acima do vencedor (price_to_win). Se sim, tenta auto-reprice dentro da banda e acima do piso configurado
Reprice
PUT /items/{id} com novo preço via ML API; grava snapshot no histórico (timestamp, preço anterior, novo, reason: auto). Cooldown de 4h por anúncio
IA Suggest
POST /api/ml/catalog/monitor/ai-suggest usa AiRepricingService com BYOK (Claude/Gemini/OpenAI do usuário via AIService). Retorna action + preço recomendado + raciocínio. Piso sempre respeitado: max(suggested, floor_price)
Alerta
Quando auto-reprice não consegue vencer Buy Box nem no piso, envia alerta Telegram ao vendedor com MLB + preço vencedor + gap de preço
🌐 Vai pro Mercado Livre / Pix
GET /items/{id}/catalog_listing_status — status do catálogo + Buy Box (posição, winner_price, price_to_win)GET /items/{id}/catalog — elegibilidade, concorrentes e preço alvoPUT /items/{id} — atualiza preço do anúncio para tentar vencer o Buy Box
⚠️ AtençãoBYOK obrigatório para sugestão IA: configure chave em Perfil > Inteligência Artificial. Sem BYOK, botão IA mostra gate de ativaçãoAuto-reprice pausável por killswitch .auto_reprice_paused — admin pode desativar globalmente em emergênciaCooldown de 4h por anúncio evita flapping de preço (ML pode penalizar mudanças muito frequentes)
Extras
42

Relatório Financeiro

P&L por venda com reconciliação real contra Mercado Pago — vê net_received de cada pedido via API MP, desconta taxa ML e frete, e mostra lucro/prejuízo com devoluções e multi-conta.

Tela real de Relatório Financeiro 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa Ferramentas > Relatório Financeiro e seleciona período (30/60/90 dias ou personalizado)
2Visualiza P&L resumido: faturamento bruto, taxas ML totais, frete, devoluções e receita líquida real reconciliada com Mercado Pago
3Expande linha por linha: vê o que o MP realmente depositou (net_received), a taxa cobrada e o custo estimado
4Filtra por conta ML, status (pago/devolvido/cancelado) ou produto para análise específica
5Exporta CSV com todas as colunas para planilha ou contador
o sistema reage por baixo
⚙️ O sistema faz
Busca
Carrega pedidos do período do JSON local (ml_orders.json), filtra por status paid/shipped/delivered e datas date_closed
Reconcilia
Para cada pedido, consulta api.mercadopago.com/v1/payments (token ML) para obter net_received real — líquido após taxas ML, parcelamento e frete gratuito. Usa collector_id (underscore) como filtro
Calcula
P&L por linha: receita bruta (total_amount) - taxa ML (fee_amount) - frete (shipping_cost) - devoluções = receita líquida real. Acumula totais do período
Agrega
Consolida por conta ML, por produto e por dia — mostra evolução temporal da margem
Exporta
CSV com colunas: data, pedido, produto, bruto, taxa, frete, net_received, status — UTF-8 com BOM para Excel
🌐 Vai pro Mercado Livre / Pix
GET api.mercadopago.com/v1/payments?collector_id={}&date_approved.range.begin={} — net_received real por pagamentoGET /orders/{order_id}/billing — detalhes de cobrança do pedido (taxa ML, breakdown)
⚠️ Atençãonet_received do MP chega em parcelas (parcelado) — relatório mostra total da venda, mas saldo MP cai gradualmentecollector.id (com ponto) causa 400 silencioso no MP; usar collector_id (com underscore) no filtroDevoluções aparecem com net_received negativo — reduz o P&L total corretamente
43

NF-e Automática

Emissão de Notas Fiscais Eletrônicas (NF-e) via gateway PlugNotas — por venda do vendedor e por custo do pedido drop — com suporte multi-CNPJ.

/ferramentas/nfe /drop/nfe · clique pra abrir (já logado)
Tela real de NF-e Automática 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa Ferramentas > NF-e e configura CNPJ de emitente (ou cada loja drop no subdomain fornecedor)
2Visualiza pedidos pagos aguardando NF-e — clica em Emitir para lançar via gateway PlugNotas
3NF-e gerada em segundos (sandbox) ou minutos (produção); status atualiza automaticamente (autorizada/rejeitada)
4Baixa o DANFE (PDF) e XML da NF-e diretamente no painel
5Para pedidos drop, o fornecedor emite NF de custo separada — vendedor vê as duas NFs no detalhe do pedido
o sistema reage por baixo
⚙️ O sistema faz
Configura
Armazena CNPJ, certificado digital (A1 .pfx), regime tributário e dados do emitente por conta (multi-CNPJ suportado)
Emite
Chama API PlugNotas (POST /nfe) com dados do pedido: destinatário, produtos, NCM/CEST, valores, frete. Aguarda callback ou polling de status
Armazena
Salva chave NF-e (44 dígitos), DANFE URL e XML no pedido local. NF-e de custo drop fica separada no registro do pedido drop
Notifica
Quando autorizada, envia link DANFE ao comprador via mensagem pós-venda ML (opcional)
🌐 Vai pro Mercado Livre / Pix
POST PlugNotas API /nfe — emissão NF-e (gateway fiscal externo, não API ML)POST /messages/packs/{pack_id}/sellers/{seller_id}/messages — envia DANFE ao comprador via chat ML
⚠️ AtençãoCertificado A1 (.pfx) tem validade — sistema alerta 30 dias antes do vencimento. Sem certificado válido, emissão falhaProdução requer contrato com gateway fiscal (PlugNotas/Nuvem Fiscal); sandbox é gratuito. Configure em Ferramentas > NF-e > GatewayNCM obrigatório: sem NCM no produto, NF-e é rejeitada pela SEFAZ. Configure em Dados Fiscais antes de emitir
Mercado Livre
44

Uber Direct — Entrega Express

Despachar pedidos via Uber Direct (entrega on-demand no mesmo dia) direto do painel — com rastreamento em tempo real e cobrança automática.

/uber /admin/pedidos (badge Turbo) · clique pra abrir (já logado)
Tela real de Uber Direct — Entrega Express 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1No detalhe de um pedido, clica em "Despachar via Uber Direct" (disponível para pedidos Flex Turbo)
2Confirma endereço de coleta, endereço de entrega do comprador e valor do frete
3Sistema cria corrida no Uber Direct e exibe link de rastreamento em tempo real
4Comprador recebe atualização de status em tempo real via WhatsApp (quando configurado)
5Admin vê badge "Turbo" laranja nos pedidos despachados via Uber Direct em /admin/pedidos
o sistema reage por baixo
⚙️ O sistema faz
Cria corrida
POST /deliveries na API Uber Direct (UBER_CLIENT_ID/SECRET do .env) com pickup_address, dropoff_address e manifest (descrição do item)
Monitora
Webhook Uber Direct atualiza status da corrida (enroute_to_pickup → arrived_at_pickup → enroute_to_dropoff → delivered) no pedido local
Notifica
Envia link de rastreamento ao comprador via WhatsApp transacional quando corrida inicia
Registra
Grava delivery_id, status e custo real da corrida no pedido (ultra_direct_delivery_id). Badge Turbo aparece em /admin/pedidos
🌐 Vai pro Mercado Livre / Pix
POST api.uber.com/v1/customers/{customer_id}/deliveries — cria corrida Uber DirectGET api.uber.com/v1/customers/{customer_id}/deliveries/{delivery_id} — status da corrida
⚠️ AtençãoDisponível apenas para pedidos com Flex Turbo — item precisa ter tag "Turbo" ativada no anúncioUBER_CLIENT_ID e UBER_CLIENT_SECRET devem estar configurados no .env — sem eles botão fica ocultoCobertura Uber Direct limitada a regiões metropolitanas — verificar disponibilidade antes de ativar para o vendedor
Fornecedor
45

Dashboard do Fornecedor

Visão consolidada das operações do fornecedor: pedidos de revenda pendentes, faturamento do mês, vendedores ativos e alertas de estoque baixo.

drop.rallydevendas.com.br/dashboard
Tela real de Dashboard do Fornecedor 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Fornecedor acessa drop.rallydevendas.com.br/dashboard com seu login (role=drop)
2Vê 4 KPIs: pedidos pendentes de pagamento, pedidos a despachar, receita do mês e vendedores ativos
3Verifica alertas: produtos com estoque abaixo do mínimo configurado e pagamentos em atraso
4Acessa atalhos rápidos: Pedidos, Catálogo, Financeiro, Integrações
5Usa o botão "Entrar como Vendedor" no sidebar para alternar entre a conta fornecedor e a conta vendedor (quando o fornecedor também é vendedor)
o sistema reage por baixo
⚙️ O sistema faz
Autentica
Valida role=drop na sessão; redireciona outros roles para seu subdomain correto (vendedor→/painel, admin→/admin)
Agrega
Conta pedidos drop por status (pending_payment, paid, dispatched), calcula receita do mês somando drop_orders aprovados
Alerta
Lista produtos com stock_quantity < min_stock_alert (configurável por produto) e pedidos com status pending_payment > 3 dias
⚠️ AtençãoVendedores vinculados ao fornecedor são gerenciados pelo admin — fornecedor não adiciona vendedores sozinhoEstoque no catálogo drop é independente do estoque ML — queda a zero não pausa anúncios automaticamente (alerta manual)
46

Catálogo do Fornecedor

Fornecedor gerencia catálogo de produtos (fotos, preço de custo, estoque, descrição) visível para vendedores vinculados — edições propagam automaticamente para anúncios ML dos vendedores.

drop.rallydevendas.com.br/produtosdrop.rallydevendas.com.br/produtos/novodrop.rallydevendas.com.br/produtos/{id}
Tela real de Catálogo do Fornecedor 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa /drop/produtos e vê lista de produtos com estoque e status de visibilidade
2Cria produto preenchendo nome, categoria, SKU, preço de custo, estoque, EAN e fazendo upload de até 6 fotos
3Define preço de custo e estoque mínimo para alertas de reposição
4Ativa/desativa visibilidade do produto na vitrine dos vendedores (toggle visível/oculto)
5Quando edita produto (título/fotos/descrição/preço), sistema propaga automaticamente para os anúncios ML dos vendedores preservando a margem de cada um
o sistema reage por baixo
⚙️ O sistema faz
Persiste
Salva produto em storage/json_db/users/{dropId}/products.json com foto em public/uploads
Propaga
Quando produto é editado, DropPushAllService propaga para os anúncios ML dos vendedores vinculados via PUT /items/{id} — preservando margem do vendedor
Decrementa
Ao confirmar pedido drop (status=paid), decrementa estoque do produto no catálogo do fornecedor
🌐 Vai pro Mercado Livre / Pix
PUT /items/{id} — quando propagando edição de produto para anúncios dos vendedores (via DropPushAllService)
⚠️ AtençãoPropagar edição para produto com 100+ vendedores vinculados pode levar alguns minutos (propagação síncrona)Estoque do catálogo drop é independente do estoque ML — zerar estoque não pausa anúncios dos vendedores automaticamente
47

Pedidos Drop

Fornecedor recebe, confere e despacha pedidos de revenda dos vendedores — com upload de etiqueta/NF, confirmação de pagamento PIX e histórico de status.

drop.rallydevendas.com.br/pedidosdrop.rallydevendas.com.br/pedidos/{id}
Tela real de Pedidos Drop 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Recebe notificação WhatsApp/Telegram quando vendedor faz pedido de compra novo
2Acessa /drop/pedidos e vê pedidos por status: aguardando pagamento, pago, despachado, entregue
3Verifica comprovante PIX do vendedor e confirma pagamento recebido
4Prepara e despacha o produto, faz upload da etiqueta de transporte e NF de custo
5Vendedor recebe notificação de despacho e pode acompanhar rastreio pelo painel
o sistema reage por baixo
⚙️ O sistema faz
Recebe
Novo pedido drop criado quando venda de anúncio de revenda entra como paga. DropOrderService::processNewMlOrders detecta via drop_origin no anúncio
Notifica
Envia alerta ao fornecedor (WhatsApp e/ou Telegram) com produto, quantidade, endereço de entrega do comprador ML e prazo de despacho
Confirma
Fornecedor confirma pagamento recebido (ou verifica comprovante PIX); status muda para paid — despacho autorizado
Despacha
Upload de etiqueta PDF e NF-e de custo no pedido. Status atualiza para dispatched; vendedor recebe notificação automática
⚠️ AtençãoPrazo ML corre: fornecedor deve despachar em até 2 dias úteis após pagamento confirmado para não afetar reputação do vendedorPedidos sem drop_origin (anúncio não vinculado ao catálogo) não geram pedido drop — vendedor deve vincular o anúncio primeiro
48

Financeiro do Fornecedor

P&L dos pedidos drop: receita, status de pagamento PIX dos vendedores e relatório do período — com visão de margem de cada lado (fornecedor e vendedor).

drop.rallydevendas.com.br/financeiro
Tela real de Financeiro do Fornecedor 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa /drop/financeiro e seleciona período (30/60/90 dias)
2Vê resumo: total faturado, pedidos pagos, pendentes e margem média da carteira
3Filtra por vendedor ou produto para ver rentabilidade individual
4Exporta CSV com pedido, vendedor, produto, preço de custo, status pagamento, data despacho
o sistema reage por baixo
⚙️ O sistema faz
Agrega
Carrega drop_orders do período, cruza com products para preço de custo
Calcula
Margem do fornecedor = preço de custo × quantidade. Margem do vendedor = (receita ML - taxa ML) - preço de custo. Mostra ambos os lados
Alerta pendências
Lista pedidos com payment_status=pending_payment há >48h como alertas de cobrança para o fornecedor
⚠️ AtençãoMargem do vendedor é estimada (Rally não tem acesso ao net_received real do vendedor via MP) — é indicativaPendências de pagamento PIX são cobradas diretamente — Rally não intermedia pagamentos entre vendedor e fornecedor
49

Integrações do Fornecedor

Conectar Mercado Pago via MP Connect para receber pagamentos dos vendedores diretamente, com geração automática de link de cobrança por pedido.

drop.rallydevendas.com.br/integracoesdrop.rallydevendas.com.br/integracoes/mercadopago
Tela real de Integrações do Fornecedor 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa /drop/integracoes e vê cartões de integrações disponíveis
2Clica em Conectar Mercado Pago e autoriza via OAuth MP para receber pagamentos
3Após conexão, pedidos com payment_method=mercado_pago geram link de pagamento automático para o vendedor
4Acompanha status de cada cobrança no painel de integrações
o sistema reage por baixo
⚙️ O sistema faz
OAuth MP
Fluxo OAuth Mercado Pago: authoriza acesso, armazena collector_id e access_token criptografado (AES-256)
Link pagamento
Quando pedido criado com MP, gera preference MP (POST /checkout/preferences) com valor do custo + dados do vendedor como pagador
🌐 Vai pro Mercado Livre / Pix
POST api.mercadopago.com/checkout/preferences — gera link de pagamento MP para o vendedor pagar custo do pedido
⚠️ AtençãoMP Connect requer aprovação de aplicativo no painel MP — processo leva 1-3 dias úteisTaxas MP (3-4% por transação) são descontadas do fornecedor — preço de custo deve considerar esse custo
Gerente de Contas
50

Dashboard do Gerente

Gerente de contas acompanha em tempo real a performance da carteira de vendedores — KPIs consolidados, alertas de saúde e acesso rápido às contas individuais.

gc.rallydevendas.com.br/dashboard
Tela real de Dashboard do Gerente 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Gerente acessa gc.rallydevendas.com.br/dashboard com login (role=gerente)
2Vê KPIs da carteira: total de vendedores ativos, faturamento consolidado do mês, pedidos totais e alertas críticos
3Identifica vendedores com queda de performance ou contas ML desconectadas (alerta em vermelho)
4Clica em um vendedor para ver detalhes da conta ou acionar impersonation (ver como o vendedor)
5Usa o switch "Entrar como Vendedor" no sidebar do GC para alternar entre as contas (vendedor → GC e vice-versa)
o sistema reage por baixo
⚙️ O sistema faz
Carrega carteira
VisibilityService retorna vendedores vinculados ao gerente via bindings.json — respeitando escopo multi-tenant
Agrega KPIs
Para cada vendedor, soma faturamento e pedidos do mês (usando date_closed). Calcula totais da carteira com AggregateCache
Detecta alertas
Marca vendedores com: token ML expirado, reputação vermelha, pedidos atrasados >48h ou sem vendas nos últimos 7 dias
Switch sidebar
No painel vendedor (subdomain painel), gerente vê botão "Entrar como Gerente" para ir ao GC. No GC, vê "Entrar como Vendedor"
⚠️ AtençãoGerente só vê vendedores de sua carteira (bindings.json) — vínculos são criados pelo admin em /adminDados carregam com AggregateCache — podem ter delay de até 5 min vs tempo real
51

Carteira de Vendedores (GC)

Gerente visualiza, monitora e acessa contas individuais da carteira — com métricas por vendedor, saúde ML, histórico de contatos e semáforo de status.

gc.rallydevendas.com.br/lojasgc.rallydevendas.com.br/lojas/{id}
Tela real de Carteira de Vendedores (GC) 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa /gc/lojas e vê cartões de vendedores com: nome, plano, faturamento do mês, contas ML e status (semáforo)
2Filtra por status (ativo/alerta/crítico), plano ou período de inatividade
3Clica em um vendedor para ver perfil detalhado: contas ML, pedidos recentes, reputação e histórico de contatos
4Adiciona nota de acompanhamento (follow-up: ligação, mensagem, visita) na conta do vendedor para registro interno
5Envia notificação push ou WhatsApp diretamente ao vendedor pelo painel
o sistema reage por baixo
⚙️ O sistema faz
Lista
Carrega vendedores via VisibilityService + dados agregados de faturamento e reputação de cada um
Classifica
Semáforo: verde (ativo+reputação boa), amarelo (sem venda 7d ou token quase expirando), vermelho (reputação ruim ou desconectado)
Follow-up
Gerente registra notas de contato com vendedor (tipo + data + descrição) — salvas no histórico de follow-ups
⚠️ AtençãoDados de vendedores carregam com AggregateCache — podem ter delay de até 5 min vs dados em tempo real
52

Relatórios GC

Relatórios consolidados da carteira: faturamento por vendedor, evolução temporal, ranking e exportação para análise gerencial.

gc.rallydevendas.com.br/relatorios
Tela real de Relatórios GC 📸 Tela real · clique pra ampliar
👤 Você faz e vê
1Acessa /gc/relatorios e seleciona período (semana/mês/trimestre)
2Vê ranking de vendedores por faturamento com variação vs período anterior
3Exporta CSV consolidado da carteira para repassar à diretoria da agência
o sistema reage por baixo
⚙️ O sistema faz
Consolida
Itera sobre vendedores da carteira, agrega faturamento e pedidos por período usando date_closed para status paid/shipped/delivered
Rankeia
Ordena por faturamento decrescente, calcula delta percentual vs período anterior para cada vendedor
Exporta
CSV: vendedor, plano, contas_ml, faturamento, pedidos, ticket_medio, variacao_% — filtrado pelo escopo do gerente
⚠️ AtençãoRelatório respeita escopo do gerente — nunca inclui vendedores de outra carteira
Gestão
53

Produtos & Estoque

Central única (em abas) onde o vendedor cadastra produtos locais do Rally, controla estoque e movimentações, importa/exporta em massa via CSV e — se tiver fornecedor vinculado — navega o catálogo do fornecedor para criar anúncios. É o cadastro-base que abastece a criação de anúncios; preço de venda NÃO mora aqui, só custo e estoque.

👤 Você faz e vê
1No menu lateral, abra o grupo 'Gestão' e clique em 'Produtos & Estoque' (ícone de caixa) — a tela abre na aba Produtos com 3 KPIs: total de produtos, ativos e rascunhos.
2Na aba Produtos, veja a prévia dos 20 primeiros itens (foto, título, SKU, custo, estoque, status). Clique em 'Novo Produto' para abrir o cadastro (/produtos/criar) ou 'Gerenciar' para a lista completa (/produtos); clique num produto para abrir o detalhe/edição.
3Troque para a aba Estoque para ver as últimas 20 movimentações (entradas/saídas, quantidade, motivo). Use 'Nova Movimentação' / 'Histórico Completo' (/estoque) para registrar ajustes manuais.
4Na aba Importar / Exportar, baixe o modelo CSV, importe produtos em massa (/produtos/importar com preview antes de confirmar), exporte seu catálogo (/produtos/exportar) ou importe ajustes de estoque (/estoque/importar).
5Se você tiver fornecedor(es) drop vinculado(s) e com produtos ativos, aparece a aba 'Catálogo Fornecedor': filtre por fornecedor, busque por nome/SKU e clique em 'Anunciar' para criar um anúncio já apontando product_id + drop_id.
6Para estoque distribuído em vários depósitos/Full/Flex no mesmo anúncio ML, use o link Estoque Multi-Origem (/estoque/multi-origem) — só funciona em contas ML com multiwarehouse habilitado.
o sistema reage por baixo
⚙️ O sistema faz
autentica
CentralProdutosController@index chama Auth::requireAuth(); resolve o user_id da sessão e monta as abas fixas (produtos, estoque, importar). A tela é o subdomínio painel.
monta-abas
Verifica Binding::getDropIdsOf(userId); se houver fornecedores vinculados, carrega DropConfig::findByOwner + Product::byUser de cada drop (só status=active e sem vitrine_hidden) e injeta a aba 'Catálogo Fornecedor' dinamicamente.
renderiza-shell
A view central/produtos.php é um shell Alpine.js com tablist; cada aba carrega seu partial (_tab_produtos / _tab_estoque / _tab_importar / _tab_catalogo). A aba ativa é sincronizada na URL via ?tab= sem recarregar a página.
carrega-produtos
_tab_produtos lê Product::byUser(userId) do JSON DB per-user (products.json), conta total/ativos/rascunhos e lista os 20 primeiros com foto (photos[0]), SKU, custo e estoque — tudo dado LOCAL, sem chamar o Mercado Livre.
carrega-estoque
_tab_estoque usa StockMovement::byUserPaginated(userId, 1, 20) para a fita de movimentações; entradas viram badge verde (+qtd) e saídas badge vermelho (-qtd). CRUD real fica no StockController (/estoque, /estoque/movimentar).
importa-exporta
_tab_importar só linka os fluxos do ImportExportController: modelo CSV (/produtos/importar/modelo), preview+confirmar (/produtos/importar/preview e /confirmar), export (/produtos/exportar) e import de estoque (/estoque/importar) — o processamento real roda nesses endpoints, não na central.
multi-origem
O link Estoque Multi-Origem aciona MultiOriginStockController, que para cada conta ML ativa com multiwarehouse habilitado descriptografa o token (MarketplaceAccount::decryptToken) e consulta os depósitos via MlMultiOriginService; gravação de qty por depósito é AJAX (MultiOriginApiTrait).
🌐 Vai pro Mercado Livre / Pix
A tela central em si NÃO chama o Mercado Livre — produtos, estoque e catálogo de fornecedor são todos dados LOCAIS do JSON DB (products.json, stock_movements.json, products do drop vinculado).Apenas a sub-tela Estoque Multi-Origem (/estoque/multi-origem) fala com o ML: lista depósitos/origens via MlMultiOriginService (User Products / stock locations) e grava quantidade por depósito; usa token descriptografado da conta.
⚠️ AtençãoPreço de venda NÃO existe no produto — só custo e estoque. O preço é definido no Anúncio. Quem procurar 'preço de venda' aqui não acha; cadastrar produto não publica nada no ML (status inicial é rascunho até virar anúncio).A aba 'Catálogo Fornecedor' some quando não há fornecedor drop vinculado E ativo com produtos — não é bug, é condicional (Binding + DropConfig status=active + produtos active não-hidden). Sem isso, só aparecem 3 abas.Estoque Multi-Origem só lista contas com multiwarehouse REALMENTE habilitado no ML (MlMultiOriginService::accountEnabled); contas sem User Products aparecem vazias. Cuidado: PUT /items legado em anúncio com user_product_id pode corromper o estoque multi-origem — gravar sempre pelo fluxo multi-origem, nunca pelo PUT de estoque antigo.
54

Kits & Combos

O vendedor junta 2+ produtos do próprio catálogo (ou 2-3 unidades do mesmo) num produto composto único — o custo e o estoque do kit são calculados sozinhos a partir dos componentes, pronto para virar anúncio depois.

/produtos/kits /produtos/kits (POST — criar kit) /produtos/kits/{id}/excluir (POST — excluir kit) · clique pra abrir (já logado)
👤 Você faz e vê
1Acesse 'Kits & Combos' no menu lateral (grupo Gestão). A tela mostra o formulário 'Montar kit' e a lista dos kits já criados. Se você ainda não tem produtos cadastrados, aparece um aviso para criar produto primeiro.
2Dê um nome ao kit (ex.: 'Kit 3 Camisetas Básicas') e, opcionalmente, defina o markup — deixe 0 para o canal de venda decidir o preço depois.
3Em 'Componentes', digite para buscar cada produto (autocomplete que filtra por título, ótimo para quem tem milhares de produtos), selecione-o e informe a quantidade por kit. Use 'Adicionar produto' para incluir mais itens.
4O botão 'Criar kit' só habilita quando o total de unidades é ≥ 2 e todos os produtos das linhas estão selecionados — o contador 'Total de itens' avisa em tempo real se falta algo.
5Na lista de kits, veja cada componente com foto, quantidade (ex.: '3×') e estoque individual; o sistema mostra o custo somado e o 'Estoque do kit' ao vivo (limitado pelo menor componente), com selo vermelho 'sem estoque' se algum componente zerar.
6Use 'Editar' (abre a edição do produto-kit em /produtos/{id}/editar) ou o lixeira para excluir o kit. O botão '→ Virar anúncio' aparece desabilitado, marcado como 'Em breve'.
o sistema reage por baixo
⚙️ O sistema faz
autentica
KitController::index exige login com papel admin, gerente, drop ou cliente (Auth::requireRole). Carrega os produtos do usuário (Product::byUser) e separa em type='kit' (lista de kits) vs. demais (produtos disponíveis como componentes).
monta-form
Injeta na view só id+título+custo de cada produto (prodJs) para alimentar o autocomplete Alpine 'kitForm'; pré-gera o CSRF (CSRF::field) no controller e passa como $csrfField para os forms.
valida-composicao
No POST, CompositeProductService::createKit normaliza os componentes e exige composição válida: ≥1 componente e total de unidades ≥ 2 (cobre '2-3 unidades do mesmo produto'); título obrigatório. Falha lança InvalidArgumentException que vira flash de erro.
calcula-custo
kitCost soma custo_componente × quantidade de cada item (lê cost ou cost_price do produto) e arredonda — o kit nunca guarda preço de venda, só custo (regra Rally: preço só no anúncio).
calcula-estoque
kitStock = mínimo de intdiv(estoque_componente, quantidade) entre todos os componentes; zera se algum componente acabar. A própria view recalcula esse estoque AO VIVO ao listar, refletindo o estoque atual de cada produto.
persiste
O kit é gravado como um Product comum com type='kit', SKU auto-gerado (prefixo KIT-), components[], kit_markup, cost, stock e status=active (Product::create) — mesmo store dos produtos, fonte única marketplace-agnóstica.
exclui
destroy verifica CSRF e chama Product::delete só no produto-kit; os produtos componentes NÃO são apagados (o CompositeProductService::delete reforça que só o composto sai). Após qualquer ação, redireciona para /produtos/kits com flash de sucesso/erro.
⚠️ AtençãoEsta tela é 100% local — NÃO publica nada no Mercado Livre. O botão '→ Virar anúncio' está desabilitado ('Em breve'); para anunciar o kit é preciso ir pela Central de Anúncios. Não há nenhuma chamada à API do ML aqui.Estoque do kit é derivado: é o menor intdiv(estoque, qtd) entre os componentes e zera se qualquer componente acabar. Vender o kit (deductKitSale, fase de pedido) baixa o estoque de CADA componente — não há estoque próprio do kit para ajustar manualmente.Composição inválida (menos de 2 unidades no total ou produto não selecionado em alguma linha) bloqueia o envio no front (botão desabilitado) e também no back (exceção). Se um produto componente for excluído do catálogo depois, o item aparece como 'produto (removido?)' e o custo/estoque do kit ficam distorcidos até reeditar.
55

Margem por SKU

Mostra, anúncio por anúncio, quanto sobra de líquido depois das taxas do Mercado Livre — ranqueado da pior margem para a melhor — cruzando o preço de venda com o custo cadastrado localmente para expor o gap de rentabilidade (headline Niada) sem nenhuma chamada ao vivo ao ML.

/margem · clique pra abrir (já logado)
👤 Você faz e vê
1No painel, abra o grupo 'Gestão' no menu lateral e clique em 'Margem por SKU'
2No topo, leia os 6 KPIs: anúncios ativos, líquido médio %, anúncios de baixa margem, quantos têm custo cadastrado, vínculos de fornecedor e exposição de taxa por venda (R$)
3Se nenhum anúncio tiver custo nem vínculo de fornecedor, um alerta sugere cadastrar custos em Produtos & Estoque (link direto)
4Percorra a tabela já ordenada pior-margem-primeiro: cada linha traz thumbnail, título, badge da origem do custo (Produto / SKU / Fornecedor / sem custo), tipo de anúncio (Clássico/Premium/Grátis), frete grátis, preço, taxa ML, % líquido, custo/margem e estoque
5Clique numa linha para expandir o detalhamento (preço, taxa em R$ e %, líquido, custo, lucro, unidades vendidas, estoque, tipo e SKU)
6Use os botões do detalhe: 'Editar no Rally' (abre /anuncios/{id}/editar), 'Editar no ML' (deep-link para mercadolivre.com.br/anuncios/{mlb}/modificar) ou 'Cadastrar custo' (vai para /produtos) quando o anúncio não tem custo
7Foque nas linhas em vermelho: % líquido abaixo de 65% ou margem abaixo de 10% sinalizam anúncios que estão dando pouco (ou nenhum) lucro
o sistema reage por baixo
⚙️ O sistema faz
autentica
MargemController@index chama Auth::requireAuth(); só vendedor logado acessa /margem (rota registrada em routes/painel.php, subdomínio painel)
cacheia
MargemService::forUser usa AggregateCache::remember (TTL 120s) — o agregado varre TODOS os anúncios, é pesado, então resultado fica cacheado por usuário (frescor ~2min)
indexa-custo
Monta índice de custos a partir de products.json local: por product_id e por SKU (ignora produtos com custo <= 0). Nenhuma origem externa de custo
filtra-ativos
Lê announcements.json (cache local sincronizado do ML) e considera só status='active' com price > 0; descarta pausados, encerrados e em revisão
calcula-taxa
Para cada anúncio chama MlFeeCalculatorService::calculate(price, listing_type, free_shipping) — taxa por tipo (Premium ~17%, Clássico ~13%, Grátis 0%), taxa fixa por faixa e subsídio de frete grátis. Cálculo 100% LOCAL via ml_ref_fee_structure.json, sem bater na API ML
resolve-margem
Resolve custo por prioridade: product_id → SKU → drop_origin (fornecedor = sem custo local). Calcula lucro (líquido − custo) e margem % sobre o preço; drop fica como 'fornecedor' sem número
ranqueia
Ordena pior-primeiro pela margem % (ou pelo % líquido quando não há custo) e gera o resumo: total, baixa margem (<65% líquido), com custo, vínculos drop, líquido médio e exposição total de taxa
🌐 Vai pro Mercado Livre / Pix
Nenhuma chamada ao vivo ao Mercado Livre nesta tela. Os anúncios vêm do cache local announcements.json (sincronizado por webhook/cron em outro fluxo) e as taxas são calculadas localmente via tabela de referência (MlFeeCalculatorService/ml_ref_fee_structure.json); os custos vêm de products.json. Os botões de ação apenas deep-linkam para o editor do Rally ou para o ML (mercadolivre.com.br/anuncios/{mlb}/modificar)
⚠️ AtençãoA taxa é uma ESTIMATIVA por tipo de anúncio (Premium/Clássico ~17%/13% + taxa fixa + subsídio de frete), não a taxa exata por categoria que o ML cobra. Para valor exato por categoria seria preciso MlPricingService (que chama a API ML), não usado aquiAnúncios de fornecedor (drop_origin) aparecem com badge 'Fornecedor' e margem em branco: o custo é externo e não fica no products.json do vendedor, então lucro/margem não são calculadosSem custo cadastrado em Produtos & Estoque, a coluna margem fica '—' e o ranking cai para o % líquido; KPIs 'com custo' e 'baixa margem' só fazem sentido depois de preencher os custos. Além disso o agregado é cacheado por 120s — mudanças de preço/custo recentes podem levar até ~2min para refletir
Extras
56

Macros

Automações por evento no estilo "quando acontecer X → me avise por Y": o vendedor cria regras que disparam uma mensagem automática no Telegram ou WhatsApp ao vender, receber pergunta ou logar no painel.

/macros /macros/{id}/toggle/macros/{id}/test/macros/{id}/delete · clique pra abrir (já logado)
👤 Você faz e vê
1Acesse 'Macros' (grupo Extras) no menu lateral — na 1ª visita o sistema já semeia 4 macros de exemplo (todas pausadas): venda, pergunta, resumo ao logar e concorrente baixou preço.
2Confira a faixa 'Canais' no topo: ✅/⚠️ indica se Telegram e WhatsApp estão conectados — uma macro só ativa/testa se o canal dela estiver pronto (link 'conectar' leva a /telegram, 'cadastrar' leva a /perfil).
3No formulário, preencha Nome, escolha o Gatilho (Nova venda, Nova pergunta, Ao acessar o painel, Concorrente mudou preço), o canal (Telegram/WhatsApp) e a Mensagem.
4Monte a mensagem clicando nas variáveis disponíveis do gatilho ({produto}, {valor}, {qtd}, {pergunta}, {vendas_hoje}, {preco_novo}, {concorrente}…) — elas são substituídas pelos dados reais no disparo.
5Salve (a macro nasce PAUSADA), clique em 'Testar' para receber uma mensagem de exemplo 🧪 no seu canal e, confirmado o recebimento, clique em 'Ativar'.
6Use os botões Editar (lápis), Pausar/Ativar e Excluir (lixeira) em cada card para gerenciar as macros existentes.
o sistema reage por baixo
⚙️ O sistema faz
autentica
index() exige login (Auth::requireRole admin/gerente/drop/cliente) e resolve o user_id da sessão — macros são per-user (storage/json_db/users/{id}/macros.json).
semeia
Macro::ensureExamples cria 4 macros de exemplo desativadas na 1ª visita e marca users.macros_seeded para não repetir; demais visitas só carregam a lista existente.
valida-canal
MacroService::channelReady checa pré-requisito: Telegram exige users.telegram_chat_id; WhatsApp exige users.whatsapp/phone com ≥10 dígitos. Sem isso, ativar/testar é bloqueado com hint.
salva
store() valida gatilho/canal contra Macro::TRIGGERS e Macro::CHANNELS, trunca nome (60) e mensagem (600), e cria/atualiza via JsonDatabase::forUser. Nova macro nasce enabled=false (testar antes de ativar).
testa
test() (AJAX, CSRF::validatePersistent) chama MacroService::runTest: interpola a mensagem com dados de exemplo, prefixa 🧪 [TESTE de macro] e envia DE VERDADE via NotifyDispatchService::toUser (transactional=true, fura caps anti-ban).
dispara-evento
Em eventos reais, hooks chamam MacroService::runForEvent(trigger, userId, ctx): on_sale e on_question via webhook ML (MlWebhookTopicsTrait), on_login via PainelDashboardController (1x/dia, guarda macro_login_last). Filtra macros ativas do gatilho, interpola e despacha pelo canal.
blinda
runForEvent roda dentro de try/catch que engole exceções — uma macro nunca pode quebrar o fluxo principal de venda/pergunta/login; falha de envio é silenciosa.
🌐 Vai pro Mercado Livre / Pix
Nenhuma chamada direta à API do ML. As macros on_sale/on_question são disparadas a partir do webhook do Mercado Livre (orders/questions) já processado pelo MlWebhookTopicsTrait — a macro só consome o contexto do evento.Envio das mensagens via NotifyDispatchService (Telegram Bot API / WhatsApp Blipei), modo transacional.
⚠️ AtençãoGatilho 'Concorrente mudou preço' (on_price_change) aparece no seletor e é semeado como exemplo, mas NÃO tem nenhum hook que o dispare no código — macro criada com esse gatilho nunca envia nada (só funciona no botão Testar).Canal não conectado trava tudo: sem telegram_chat_id (ou WhatsApp <10 dígitos no perfil) o botão Testar fica desabilitado e Ativar retorna erro. Conectar em /telegram ou /perfil antes.Macro de 'Ao acessar o painel' (on_login) dispara no máximo 1x por dia (trava macro_login_last com a data); não avisa a cada login do mesmo dia.
Gestão
57

LogManager (Flex)

Conectar (BYOK) o token da própria conta LogManager — a transportadora same-day homologada pelo ML por trás dos pedidos Flex Turbo — para a vitrine gerar etiquetas de Flex automaticamente e responder o rastreio do comprador direto nas mensagens do Mercado Livre, sem link nem dados pessoais.

👤 Você faz e vê
1No painel, abra o grupo 'Gestão' no menu lateral e clique em 'LogManager (Flex)' (ícone com o favicon da marca). A tela mostra o status da conexão (conectada/pendente) e dois cartões: conectar o token e preferências de mensagem ao comprador.
2Se ainda não conectou, abra 'Como pegar meu token na LogManager?' (ou o botão 'Guia passo a passo'): entre em app.logmanager.com.br › Integrações › 'Criar nova integração' › canal 'api' › Salvar › copie a 'API Key'.
3Cole a API Key no campo Token (input password, autocomplete off) e confirme/ajuste a Transportadora — o sistema já sugere o nome detectado pelo seu cadastro (CarrierLink).
4Clique em 'Testar conexão' (AJAX, throttle 3s) para confirmar que a LogManager está acessível, depois em 'Salvar token' — ele é guardado criptografado e só volta como máscara (••••1234).
5No cartão 'Rastreio nas mensagens do Mercado Livre', marque 'Responder rastreio automaticamente' (recomendado, default ON) e, se quiser, 'Avisar a previsão de entrega de forma proativa' (sancionada pelo ML, default OFF) e salve.
6Se entrou pela sua transportadora parceira, use a CTA verde '3 meses grátis' para solicitar a parceria e abrir a conversa no WhatsApp. Para desconectar, clique em 'Desconectar' (pede confirmação) — o rastreio continua funcionando mesmo sem token.
o sistema reage por baixo
⚙️ O sistema faz
autentica
index() chama Auth::requireAuth(); carrega UserLogManagerService::forView() (connected, máscara, connected_at, last_ok_at, carrier_name, prefs de mensagem) e monta CSRF::field().
sugere-transportadora
A API da LogManager não revela a transportadora pelo token, então o sistema varre CarrierLink::active() do usuário e pré-preenche o nome da transportadora vinculada no cadastro; checa referred_by_carrier e partnership_requested_at para exibir a CTA de parceria (3 meses grátis).
salva-token
POST /conectar valida CSRF, valida formato (não vazio, ≥16 chars, sem espaços) e grava em users.json › logmanager.token CRIPTOGRAFADO (AES-256-GCM, prefixo 'enc:') via Encryption::encrypt; registra evento em LogManagerLog (token mascarado). Token cru NUNCA volta ao front.
testa-sem-efeito
POST /testar (AJAX, ApiAuthMiddleware, CSRF persistente) chama LogManagerClient::ping() = GET /api/v1/shipmentsV2/0 — propositalmente SEM criar envio (o callback dispara motorista real). Qualquer HTTP (200/404/422) = host no ar; marca last_ok_at.
prefs-mensagem
POST /preferencias grava {auto_reply, proactive_eta} em users.json › logmanager.msg e mantém um índice enxuto lm_proactive_optin.json (cron lê só quem ativou ETA pró-ativa — custo zero quando ninguém ligou).
gera-etiqueta-flex
Quando há venda Flex/Turbo, o token BYOK habilita LogManagerClient::createShipment() (POST /api/integrations/erp/callback, Bearer) para criar a entrega e devolver label_url/tracking_url na conta do próprio vendedor; rate-limit real de 10 req/min por conta.
rastreio-publico
O rastreio NÃO usa este token: endpoints públicos (track por chave NFe e shipmentsV2 por id) alimentam a resposta automática ao comprador no ML, mapeando o status LogManager → status do shipment ML (entregue/a caminho/coletado etc.) sem incluir link, telefone ou e-mail.
🌐 Vai pro Mercado Livre / Pix
POST https://app.logmanager.com.br/api/integrations/erp/callback (Bearer token do vendedor) — cria a entrega Flex e devolve label_url/tracking_url (efeito colateral: dispara motorista; só no Flex real, nunca no Testar)GET /api/v1/shipmentsV2/{id} — consulta entrega por id (status + histórico + etiqueta); usado também no ping com id=0 para testar conectividade sem criar envio (público)GET /api/v1/shipments/track/{nfeKey} — rastreio pela chave da NF-e (44 dígitos): situação, comprovante, recebedor, data prevista (público, dispensa token)Mapeamento de status LogManager → ML (delivered/shipped/returning_to_sender/lost...) feito localmente para responder o rastreio dentro das mensagens do Mercado Livre
⚠️ AtençãoO botão 'Testar conexão' só confirma que a LogManager está no ar (formato do token + host alcançável) — NÃO valida que o token é válido para despachar. A validação definitiva só acontece no primeiro Flex realmente despachado pela vitrine, porque o /erp/callback cria um pedido real (motorista a caminho).Sem token conectado a vitrine deixa de gerar etiqueta de Flex automaticamente, mas o RASTREIO continua funcionando (endpoints públicos por NFe/shipment id) — não confunda 'sem conexão' com 'rastreio quebrado'.A mensagem pró-ativa de previsão de entrega (proactive_eta) começa DESLIGADA por design: ela usa a cota sancionada DELIVERY_PROMISE do ML; ligar e usar em escala sem validar numa conta de teste pode esgotar a cota. A resposta automática reativa só dispara quando o comprador pergunta e nunca inclui link/telefone/e-mail (regra de moderação do ML).
TikTok
58

TikTok Shop

Transformar um produto/anúncio do Rally em anúncio do TikTok Shop (Brasil e México): o vendedor escolhe um produto, vê uma pré-visualização do anúncio TikTok com avisos de pré-requisito, e ficará a 1 clique de publicar assim que o app de integração for aprovado no TikTok Shop Partner Center.

/tiktok/shop /tiktok/shop?id={announcement_id}/tiktok/shop?page={n} · clique pra abrir (já logado)
👤 Você faz e vê
1Ative a integração TikTok em Configurações da Conta (/central/config?tab=lojas) — só assim a seção 'TikTok' aparece no menu lateral (com Visão geral, Conteúdo, Relatórios e TikTok Shop, este com selo 'análise')
2Clique em 'TikTok Shop' no menu. A tela explica que o app está em análise no TikTok Partner Center: você já pode preparar e pré-visualizar, mas o envio libera após a aprovação
3Veja a grade dos seus anúncios do Rally (12 por página, com foto e preço) e clique em um produto para transformá-lo em anúncio do TikTok Shop
4O sistema monta a pré-visualização: nome do produto (cortado em 255 caracteres), preço em R$, estoque, atributos e até 3 imagens — espelhando como ficaria no TikTok Shop
5Leia o bloco 'Antes de publicar' com os avisos de pré-requisito (categoria a mapear, GTIN/marca por categoria, sem imagem, estoque zerado) e ajuste o produto se preciso
6Use 'Escolher outro produto' para voltar à grade, ou pagine entre seus anúncios. O botão 'Clonar pro TikTok Shop' fica desabilitado (aguardando aprovação) — nenhum dado é enviado ao TikTok por enquanto
o sistema reage por baixo
⚙️ O sistema faz
gate-menu
A seção TikTok no sidebar só renderiza se UserIntegrations::has(userId, 'tiktok') for true — flag em users.json.integrations, ligada/desligada em /central/config?tab=lojas. Sem a flag, a tela existe mas não há link no menu
autentica
TikTokController@shop chama Auth::requireRole(admin, gerente, drop, cliente) — qualquer papel logado acessa; rota GET /tiktok/shop registrada em routes/painel.php com middleware $auth
carrega
Pagina os anúncios do próprio usuário via Announcement::byUserPaginated(userId, page, 12) — 100% dados locais do Rally, ZERO chamada ao TikTok no carregamento da tela
mapeia
Ao selecionar (?id=), Announcement::findById carrega o anúncio e UnifiedListingMapper::fromAnnouncement o converte no formato unificado (title, price, stock, photos, attributes, category_hint, source_mlb)
preview
UnifiedListingMapper::tiktokShopPreview gera a pré-visualização: corta product_name em 255 chars, monta preço/estoque/atributos/imagens — tudo calculado localmente, sem tocar a API do TikTok
valida-preflight
O mapper acumula warnings de pré-requisito: título >255 chars, ausência de imagem, categoria ML a mapear para a árvore TikTok (GetCategoryTree), GTIN/marca por categoria (GetCategoryRules) e estoque zerado — exibidos no bloco 'Antes de publicar'
publish-gated
O botão 'Clonar pro TikTok Shop' renderiza com atributo disabled e title 'Disponível quando o TikTok aprovar o app'. Não existe rota de POST de publicação no TikTok Shop — o push real está desligado até a aprovação no Partner Center
🌐 Vai pro Mercado Livre / Pix
Nenhuma chamada externa em tempo real nesta tela: o picker e a pré-visualização usam só dados locais do Rally (announcements.json). O envio ao TikTok Shop (POST /products via TikTokShopClient) está implementado no service mas NÃO ligado à UI — botão desabilitado até aprovação do app
⚠️ AtençãoSe a seção TikTok não aparece no menu, a integração não foi ativada: vá em Configurações da Conta › Lojas (/central/config?tab=lojas) e ligue o TikTok (flag em users.json.integrations.tiktok)Publicação real é vaporware controlado: o botão 'Clonar pro TikTok Shop' está sempre disabled enquanto o app aguarda aprovação no TikTok Shop Partner Center. A tela só prepara e pré-visualiza — nenhum anúncio é criado no TikTok aindaA pré-visualização sai dos dados do anúncio ML local: se faltar imagem (photos[0]), categoria (category_hint) ou estoque, o produto vira avisos de pré-requisito em vez de anúncio pronto — corrija na origem (anúncio/produto) antes que o push seja liberado
Shopee
59

Shopee

Hub do marketplace Shopee dentro do painel: o vendedor pega um produto do Rally e vê em tempo real como o anúncio sairia na Shopee (nome ≤120, preço, estoque, fotos, atributos + avisos de pré-requisito) antes de publicar. O envio e o painel de pedidos ficam travados ('planejado / em breve') até o conector Shopee Open Platform ser ativado.

/shopee /shopee/produtos /shopee/produtos?id={announcement_id}/shopee/pedidos · clique pra abrir (já logado)
👤 Você faz e vê
1Ativa a integração Shopee em Central de Configurações › Lojas (/central/config?tab=lojas) — só então a seção 'Shopee' aparece no menu lateral (badge 'em breve').
2Abre 'Shopee › Visão geral' (/shopee): vê 3 cartões — Produtos→anúncio (preview), Pedidos (planejado) e Documentação oficial — mais um aviso de que o conector ainda não está ligado.
3Clica em 'Produtos' (/shopee/produtos) e vê a lista paginada (12 por página) dos seus anúncios do Rally com foto e preço.
4Clica num produto: o sistema converte o anúncio Rally em preview Shopee e mostra nome (cortado a 120 caracteres), preço, estoque, até 3 imagens, atributos e uma lista de avisos do que falta ajustar.
5Lê os avisos (título longo, sem foto, categoria a mapear, marca possivelmente exigida, estoque zerado) e ajusta o produto no Rally antes de publicar.
6Tenta 'Publicar no Shopee' — o botão está DESABILITADO com a etiqueta 'planejado'; o envio só liga quando o app for cadastrado no Shopee Open Platform.
7Abre 'Pedidos' (/shopee/pedidos): vê um placeholder explicando que pedidos (status, comprador, valor, faturar, etiqueta, marcar enviado) entram aqui quando o conector ativar.
o sistema reage por baixo
⚙️ O sistema faz
autoriza
MarketplaceHubController::hub/produtos/pedidos roda Auth::requireRole(admin, gerente, drop, cliente) — qualquer papel logado acessa.
resolve-marketplace
Deriva o marketplace do 1º segmento da URI (/shopee) e valida contra MarketplaceCatalog (whitelist). Se não estiver no catálogo → HTTP 404 'Marketplace não encontrado'. Config 'shopee' traz label, ícone, cor #ee4d2d, status=planejado, gated=true e gated_reason.
lista-produtos
Em /shopee/produtos chama Announcement::byUserPaginated(userId, page, 12) — pega anúncios reais do Rally do próprio vendedor, paginados, com foto (photos[0]) e preço.
monta-preview
Ao selecionar um produto (?id=), UnifiedListingMapper::fromAnnouncement normaliza o anúncio e shopeePreview gera o preview: nome=mb_substr(title,0,120), preço, estoque, fotos, atributos + avisos (título>120, sem imagem, categoria ML a mapear via get_category, marca possivelmente exigida via get_brand_list, estoque<1).
renderiza
Tudo é catalog-driven e usa as mesmas views genéricas (painel/marketplace/index.php, produtos.php, pedidos.php) compartilhadas com o Magalu — nenhuma tela exclusiva da Shopee.
gate-publish
Como gated=true / status=planejado, o botão 'Publicar no Shopee' é renderizado disabled e a tela de pedidos é só placeholder. A UI funciona (preparar/pré-visualizar), mas o push fica travado até o conector ser ativado.
menu-condicional
A seção Shopee só aparece no sidebar se UserIntegrations::has(userId,'shopee') — flag persistida em users.json › integrations.shopee, ligada/desligada em /central/config?tab=lojas.
🌐 Vai pro Mercado Livre / Pix
Nenhuma chamada à API da Shopee é feita — o conector ainda não está ativado (status=planejado, gated). O preview é 100% local, a partir de dados do anúncio do Rally.Os anúncios usados no preview vêm do cache local do Rally (announcements.json do vendedor, populado pelo sync do Mercado Livre) — não há chamada externa em tempo real.Quando ativado, a integração deverá usar o Shopee Open Platform (get_category, get_brand_list, add_item, get_order_list) — documentação oficial linkada em open.shopee.com/developer-guide/12.
⚠️ AtençãoTela gated: o botão 'Publicar no Shopee' está sempre desabilitado e Pedidos é placeholder. Falta cadastrar o app no Shopee Open Platform Console (partner_id + partner_key) e o vendedor autorizar a loja. Hoje a tela só prepara e pré-visualiza — não publica nem sincroniza.A seção Shopee fica invisível no menu até o usuário ativar a integração em Central de Configurações › Lojas (/central/config?tab=lojas) — sem isso, /shopee até responde por URL direta mas o atalho não aparece no sidebar.O preview reaproveita as views genéricas de marketplace (compartilhadas com o Magalu) e o cache local de anúncios do ML; produtos sincronizados há muito tempo ou sem foto/atributos saem com avisos no preview. Categoria e marca da Shopee ainda precisarão de mapeamento manual (get_category/get_brand_list) quando o conector ligar.
Marketplaces
60

Magalu

Hub do marketplace Magalu (Magazine Luiza) no painel: o vendedor prepara e pré-visualiza como um produto do Rally sairá como anúncio no Magalu (nome, SKU, preço, estoque, fotos, atributos + avisos fiscais/fulfillment) antes de publicar. UI 100% navegável; o envio real (publicar/sincronizar pedidos) fica travado em 'em breve' até o conector Magalu ser ativado.

/magalu /magalu/produtos /magalu/produtos?id={announcement_id}/magalu/pedidos · clique pra abrir (já logado)
👤 Você faz e vê
1Ative a integração Magalu em /central/config?tab=lojas — só então a seção 'Magalu' aparece no menu lateral (grupo Marketplaces, ícone sacola azul). Sem ativar, nada aparece.
2Clique em 'Magalu › Visão geral' (badge 'em breve'). A tela explica o status ('planejado'), o que falta para ligar o conector (app no ID Magalu + scopes + consentimento do seller no Portal Magalu) e mostra 3 cards: Produtos→anúncio (preview), Pedidos e link da Documentação oficial.
3Em 'Produtos', veja a lista paginada dos seus anúncios do Rally (12 por página, foto + título + preço) e clique em um produto para gerar o preview.
4Veja o preview do anúncio formatado para o Magalu: nome do produto, SKU, preço (R$), estoque, até 3 fotos (+contador) e os atributos — exatamente como o item sairia no portfólio Magalu.
5Leia o bloco de avisos antes de publicar (ex: 'sem SKU — o Magalu identifica pelo SKU', cadastro assíncrono HTTP 202 via webhook, NCM/dados fiscais para NF-e, definir se é fulfillment ou envio próprio).
6O botão 'Publicar no Magalu (planejado)' aparece desabilitado — liga só quando o conector for ativado. Em 'Pedidos', a tela é um placeholder que descreve o painel futuro (faturar/etiqueta/marcar enviado, espelhando o ML).
o sistema reage por baixo
⚙️ O sistema faz
deriva-marketplace
MarketplaceHubController é genérico e catalog-driven: deriva o marketplace do 1º segmento da URI (/magalu) e valida contra MarketplaceCatalog::get('magalu') (whitelist). Se não estiver no catálogo, responde 404. As rotas são registradas em loop sobre MarketplaceCatalog::all() — adicionar marketplace não cria tela nova.
autoriza
Auth::requireRole('admin','gerente','drop','cliente') nas 3 ações (hub/produtos/pedidos). A seção no sidebar é gateada por UserIntegrations::has($userId,'magalu') — flag em users.json → integrations.magalu, ligada em /central/config?tab=lojas.
carrega-config
Lê a config declarativa do Magalu do MarketplaceCatalog (label, icon ph-shopping-bag-open, cor #0086ff, regions=[Brasil], status='planejado', gated=true, gated_reason, capabilities=[produtos,pedidos], docs developers.magalu.com). Nenhuma chamada externa — config estática em PHP.
lista-produtos
Em /magalu/produtos, Announcement::byUserPaginated($userId,$page,12) carrega os anúncios do Rally do usuário (JSON DB per-user), paginado 12 por página. Foto vem de photos[0] (campo thumbnail é morto).
mapeia-unificado
Ao selecionar um produto (?id=), UnifiedListingMapper::fromAnnouncement converte o anúncio no formato canônico UnifiedProduct (title, sku, price, stock BRL, photos, attributes, category_hint, source_mlb) — o mesmo objeto que alimentaria todos os adapters (TikTok/Shopee/Magalu).
gera-preview
Chama UnifiedListingMapper::magaluPreview (resolvido via mk.preview_fn) que monta o preview específico do Magalu e a lista de warnings (SKU obrigatório, ≥1 imagem, cadastro assíncrono 202+webhook, NCM/fiscal NF-e, fulfillment vs envio próprio, estoque>0). Tudo local, sem rede.
trava-publicacao
Como gated=true, o botão 'Publicar' renderiza disabled e a aba Pedidos é um placeholder estático. Não há POST de publicação nem sync de pedidos — o conector Magalu ainda não está implementado (backend de publish/orders inexistente).
🌐 Vai pro Mercado Livre / Pix
Nenhuma chamada externa real nesta tela. O preview é gerado 100% local a partir dos anúncios já existentes no Rally (UnifiedListingMapper).Endpoints Magalu citados apenas como AVISO no preview (não chamados): cadastro de SKU de portfólio é assíncrono (HTTP 202 + confirmação por webhook); ref. oficial developers.magalu.com/docs/apis. A autenticação seria via app no ID Magalu (client_id+secret IDM CLI) + consentimento do seller — ainda não configurado.
⚠️ AtençãoVaporware parcial: a publicação real e o painel de pedidos NÃO existem (botão 'Publicar' fica disabled, /magalu/pedidos é placeholder). Só preview de produto funciona de verdade. Status 'planejado'/'em breve'.A seção Magalu só aparece no menu se UserIntegrations.magalu=true (ativar em /central/config?tab=lojas). Sem isso, as rotas /magalu existem mas nada no sidebar leva a elas — vendedor 'não acha'.Preview puxa anúncios do Rally; se o usuário não tem anúncios, a tela de produtos mostra empty-state ('crie ou sincronize produtos primeiro'). Sem SKU no produto, o aviso lembra que o Magalu identifica o item do portfólio pelo SKU — preview funciona, mas publicar (quando ligar) exigiria SKU.
Vitrine
61

Cupons da Loja

O vendedor cria e gerencia cupons de desconto da sua loja própria (vitrine com checkout) — percentual, valor fixo em reais ou frete grátis — com regras de pedido mínimo, validade e limite de usos, que o comprador aplica no carrinho durante o checkout.

/loja/cupons /loja/cupons/criar /loja/cupons/{id}/toggle/loja/cupons/{id}/excluir · clique pra abrir (já logado)
👤 Você faz e vê
1No painel, abra o grupo 'Vitrine' no menu lateral e clique em 'Cupons' (ícone de ticket). A tela mostra o formulário 'Novo cupom' no topo e a tabela com os cupons já criados (ou um estado vazio convidando a criar o primeiro)
2Preencha o formulário: Código (ex: BEMVINDO10, digitado em maiúsculas), Tipo (% de desconto, R$ de desconto ou Frete grátis), Valor, Pedido mínimo em R$, Máx. usos (0 = ilimitado) e Validade opcional
3Clique em 'Criar cupom' — ele aparece na tabela já ativo; o sistema mostra um aviso verde 'Cupom criado!' (ou 'Informe o código e um valor válido' se faltar dado)
4Na tabela, veja por cupom: código, tipo de desconto, mínimo, usos atuais/máximo, validade e status. Clique no botão de status (Ativo/Inativo) para ligar ou pausar o cupom sem excluí-lo
5Para remover de vez, clique na lixeira — pede confirmação ('Excluir este cupom?') antes de apagar
6O comprador, no checkout público da sua loja, digita o código do cupom no carrinho; o desconto (ou frete grátis) é aplicado em tempo real e o contador de 'usos' do cupom sobe quando o pedido é fechado
o sistema reage por baixo
⚙️ O sistema faz
autentica
Auth::requireRole(...ROLES) garante que só o dono logado acessa /loja/cupons; pega o user_id da sessão como sellerId. Mesmas ROLES e guardPost() reaproveitados do PainelStoreOrdersController (CSRF obrigatório em todo POST)
lista
StoreCouponService::bySeller lê a coleção user-scoped store_coupons via JsonDatabase::forUser(sellerId)->readAll — cada vendedor só vê e edita os próprios cupons (multi-tenant por sharding JSON)
cria
couponCreate normaliza o código (uppercase, sem espaços), valida o tipo contra a whitelist [percent, fixed, free_ship], arredonda valor/mínimo, força max_uses>=0 (0=ilimitado), zera 'used' e grava active=true. Exige código + (valor>0 OU tipo=free_ship)
ativa-pausa
couponToggle faz update do campo active no JSON (true/false) — pausa o cupom sem perder histórico de usos; couponDelete remove o registro definitivamente
valida-checkout
No checkout público, POST /checkout/coupon chama StoreCouponService::validate(sellerId, code, subtotal): confere se existe, está ativo, não expirou (expires_at), não esgotou (used < max_uses) e atinge o pedido mínimo; calcula o desconto e devolve JSON com label amigável
aplica-no-pedido
StoreCheckoutService::place RE-valida server-side via StoreCouponService::apply: recalcula desconto/frete grátis sobre o subtotal real e chama recordUse() para incrementar o contador de usos do cupom — nunca confia só na validação do front
renderiza
A view painel/loja/cupons.php monta a tabela responsiva (vira cards no mobile <=760px), sanitiza todo output com htmlspecialchars(ENT_QUOTES) e renderiza dentro de layouts/app.php; flash de sucesso/erro vem da sessão
⚠️ AtençãoSem chamadas ao Mercado Livre — esses cupons valem SÓ na vitrine/loja própria do vendedor (checkout direto). Não têm relação com os cupons do ML, que ficam em outra tela (/api/ml/coupons via MlApiExtendedController)A validação no front (POST /checkout/coupon) é só UX; a verdade é a re-validação em StoreCheckoutService::place. O contador 'usos' só sobe quando o pedido é efetivamente fechado, não quando o comprador apenas digita o códigoFrete grátis (free_ship) não exige valor, mas os tipos percent/fixed exigem valor>0 — caso contrário o couponCreate recusa com 'Informe o código e um valor válido'. Código é sempre normalizado em MAIÚSCULAS sem espaços, então 'bemvindo 10' e 'BEMVINDO10' colidem
Crescimento
62

Meu Pódio

Vitrine de gamificação do vendedor — mostra nível atual (Iniciante→Diamante), pontos acumulados, barra de progresso pro próximo nível, streak de semanas em alta e o grid das 10 conquistas (badges) desbloqueadas/bloqueadas, tudo calculado a partir da qualidade dos anúncios e do histórico de vendas no ML, sem cobrar nada nem chamar IA.

/conquistas · clique pra abrir (já logado)
👤 Você faz e vê
1No menu lateral do painel, abra o grupo 'Crescimento' e clique em 'Meu Pódio' (ícone de troféu) — leva para /conquistas
2Veja no topo (hero) seu nível atual com medalha/emoji, total de pontos formatado e a barra mostrando quantos pontos faltam pro próximo nível (ou '🎉 Você chegou ao nível máximo!' no Diamante)
3Confira as 4 mini-estatísticas: nº de conquistas desbloqueadas, anúncios ativos, semanas consecutivas em alta (🔥 streak) e score médio dos anúncios
4Role até o grid de conquistas: badges desbloqueadas aparecem coloridas com ✓ e rótulo 'Desbloqueada'; as bloqueadas ficam em cinza (grayscale) com cadeado 🔒 e 'Bloqueada'
5Suba de nível vendendo mais e melhorando seus anúncios — a página é só leitura/consulta, não tem botões de ação nem formulários (gamificação puramente informativa)
o sistema reage por baixo
⚙️ O sistema faz
autentica
Auth::requireRole('admin','gerente','drop','cliente') — qualquer papel logado acessa; pega o user_id da sessão. Sem PlanGuard: a tela não é feature paga.
cache
SellerGamificationService::forUser() serve de cache local storage/cache/gamification_{userId}.json com TTL de 30min (1800s); só recomputa se expirado ou força. Invalidate() apaga o arquivo.
pontos-qualidade
Percorre Announcement::byUser, filtra só status='active' com marketplace_item_id, e soma o score (0-100) de cada um via AnnouncementDiagnosticService::analyze() — calculado LOCALMENTE da dados em cache do anúncio (descrição, fotos, atributos, logística, promo), sem chamar o ML.
pontos-vendas
computeSalesContext() lê ml_orders.json local: +10 pts por pedido em 90d e +1 pt a cada R$10 faturados em 90d. Usa date_closed quando status∈{paid,shipped,delivered}, senão date_created; ignora cancelled/invalid.
niveis
Soma pontos (qualidade+vendas) e resolve o nível na escala fixa LEVELS: 🌱 Iniciante 0 · 🥉 Bronze 500 · 🥈 Prata 2.000 · 🥇 Ouro 5.000 · 💎 Platina 15.000 · 👑 Diamante 30.000; calcula próximo nível, pts_to_next e progress_pct.
conquistas
computeBadges() avalia 10 badges sobre o total histórico (lifetime): 1ª venda, 10/100 pedidos, R$1k/10k/50k faturados, ativo 90d, 30+ pedidos em 90d, 30/90 dias vendendo. Cada uma vira unlocked=true/false.
streak
computeStreakWeeks() agrupa ml_orders por semana (ISO o-W), soma faturamento por semana e conta semanas consecutivas com receita maior que a anterior, de trás pra frente — esse é o número '🔥 semanas em alta'.
renderiza
PainelConquistasController seta $g e require da view painel/conquistas.php, que monta hero+stats+grid em CSS BEM/tokens dentro do layout app.php. Empty-state amigável quando não há badges ('Conecte sua conta ML e comece!').
⚠️ AtençãoPontos/badges/streak refletem o cache de 30min (gamification_{userId}.json) E o cache de ml_orders/announcements — vendas recém-sincronizadas só aparecem após o TTL expirar ou SellerGamificationService::invalidate() ser chamado; não há refresh ao vivo na tela.Score de qualidade só conta anúncios com status='active' e marketplace_item_id preenchido — vendedor com tudo pausado/encerrado ou sem conta ML conectada vê 0 pontos de qualidade e fica no nível Iniciante mesmo tendo vendido.A escala de níveis na constante LEVELS do service (Bronze=500, Prata=2.000) diverge do comentário/docstring do topo do arquivo (que cita Bronze=2.000, Prata=5.000) — o que vale é o array LEVELS; ao mexer em thresholds, conferir o array, não o comentário.
Extras
63

Telegram

O vendedor pareia sua conta Rally com o bot do Telegram (@rallydevendas_bot) para receber alertas (vendas, perguntas, lembretes) e conversar com o assistente direto no chat — gera um código de 6 caracteres, manda /link CODIGO no bot e pronto.

👤 Você faz e vê
1Acesse 'Telegram' no grupo Extras do menu lateral. A tela mostra um cartão com o status de conexão: conectado (mostra o chat_id) ou ainda não pareado
2Se não estiver conectado, clique no botão azul 'Abrir bot (@rallydevendas_bot)' que leva direto pro chat do bot no Telegram (https://t.me/rallydevendas_bot)
3Clique em 'Gerar código' — o sistema cria um código de 6 caracteres (ex: A1B2C3) e mostra na tela com botão de copiar
4No chat do bot, mande a mensagem /link CODIGO (substituindo CODIGO pelo gerado). O bot confirma com '✅ Conectado, [seu nome]!'
5De volta na tela, o cartão passa a exibir 'Conectado' com o chat_id; mande /ajuda no bot pra ver os comandos disponíveis
6Para desfazer, clique em 'Desconectar' (pede confirmação) — limpa o vínculo e o bot para de enviar mensagens
o sistema reage por baixo
⚙️ O sistema faz
autentica
Auth::requireRole('admin','gerente','drop','cliente') — qualquer papel logado acessa /telegram (middleware $auth na rota)
carrega-estado
ChatState::get(userId) lê o registro único chat_state.json do usuário (per-user shard) e extrai telegram_chat_id (vínculo ativo) e telegram_link_code (código pendente)
resolve-bot
Lê TELEGRAM_BOT_USERNAME do .env (fallback 'rallydevendas_bot') pra montar o deep-link https://t.me/{bot} e o CTA azul de abrir o chat
gera-codigo
POST /telegram/gerar: CSRF::verify, gera código de 6 hex (strtoupper(substr(bin2hex(random_bytes(4)),0,6))) e grava via ChatState::setTelegramLinkCode; redireciona pra /telegram?code=XXXXXX
parea-no-bot
Quando o usuário manda /link CODIGO no Telegram, o TelegramWebhookController (trait TelegramCommandsTrait::doLink) faz ChatState::findByTelegramLinkCode (varredura linear de todos os users), e ao achar chama ChatState::linkTelegram(userId, chatId) — grava telegram_chat_id e zera o link_code
confirma
Bot responde '✅ Conectado, [nome]!' no chat; na próxima visita à tela /telegram o cartão renderiza o estado conectado com o chat_id
desconecta
POST /telegram/desconectar: CSRF::verify, zera telegram_chat_id e telegram_link_code no chat_state via JsonDatabase::forUser(userId)->upsert; redireciona pra /telegram?disconnected=1 com alerta de sucesso
🌐 Vai pro Mercado Livre / Pix
Sem chamadas ao Mercado Livre — esta tela é só pareamento Rally↔Telegram.O envio efetivo de mensagens é feito pela API do Telegram (Bot API sendMessage), via TelegramNotifyService/webhook, fora desta tela. As preferências de quais notificações chegar ficam em /perfil#telegram (telegram_notif_prefs).
⚠️ AtençãoTELEGRAM_BOT_USERNAME ausente no .env: a tela cai no fallback hardcoded 'rallydevendas_bot' — se o bot real tiver outro username, o deep-link 'Abrir bot' aponta pro bot errado e o /link nunca casaO código de pareamento NÃO expira nem é de uso único no lado do bot (findByTelegramLinkCode só compara igualdade) — gerar um novo código sobrescreve o antigo, mas códigos antigos ficam válidos até serem sobrescritos; o vínculo é por chat_id (1 Telegram = 1 conta Rally via última vinculação)Existe um segundo fluxo de pareamento legado em /perfil (telegram-link/unlink via deep-link ?start=TOKEN, grava telegram_chat_id direto em users.json, com expiração de 600s) — coexiste com este (que grava em chat_state.json). São stores diferentes; desconectar numa tela não necessariamente limpa o vínculo da outra
Operações
64

Gestão Flex

O gerente (ou admin/fornecedor) acompanha num só painel TODOS os pedidos Flex e Turbo (same-day) dos seus vendedores visíveis — separados por etapa logística (a despachar, a caminho, entregue, problema) — imprime etiquetas e confere o estado da integração LogManager por vendedor, sem precisar entrar conta a conta.

gc.rallydevendas.com.br/flexgc.rallydevendas.com.br/flex?bucket=a_despachar&seller_id={id}&q=&turbo=1gc.rallydevendas.com.br/flex/ordersgc.rallydevendas.com.br/flex/transportadoresgc.rallydevendas.com.br/flex/transportadores?seller_id={id}
👤 Você faz e vê
1No menu lateral do Gerente de Contas, grupo 'Operações', clica em 'Gestão Flex' (ícone raio). Abre o painel com 5 cartões de métrica: total Flex/Turbo, a despachar, a caminho, Turbo same-day e receita Flex.
2Usa as abas (pílulas) para filtrar por etapa logística: Todos, A despachar, A caminho, Entregue, Problemas — cada aba mostra a contagem de pedidos entre parênteses.
3Refina com os filtros: escolhe um vendedor específico no seletor (só aparece se há mais de um), digita no campo de busca (pedido, comprador, item, SKU ou shipment) ou marca 'Só Turbo' para ver apenas same-day.
4Na tabela vê cada pedido com comprador, vendedor, selo Flex ou Turbo, valor e status logístico colorido. Para pedidos em 'A despachar' ou 'A caminho' com envio gerado, clica em 'Etiqueta' para abrir/imprimir a etiqueta do Mercado Livre em nova aba.
5Clica no botão 'Transportadores' (topo) para ver, por vendedor, se o token LogManager está conectado e quantas transportadoras estão vinculadas.
6Clica em 'Detalhe' de um vendedor para abrir o card da integração LogManager (status, token mascarado, último OK), as transportadoras vinculadas (com selo LogManager) e o log ao vivo do processo de integração (conexão de token, chamadas de API, criação de envio, rastreio, erros).
o sistema reage por baixo
⚙️ O sistema faz
autoriza
Auth::requireRole('admin','gerente','drop') no controller; o gate de rota /gc/flex (AuthMiddleware + RBACMiddleware) só admite admin e gerente no subdomínio gc. VisibilityService resolve QUAIS vendedores o viewer enxerga (admin=todos, gerente=vinculados) — NUNCA usa Auth::id() como dono dos pedidos.
resolve-seller
Lê ?seller_id opcional e valida com VisibilityService::canSeeUser — guarda anti-IDOR: se o seller não for visível ao viewer, devolve 403 e ignora o filtro (cai para 'todos visíveis').
agrega
FlexOrdersAggregator::forViewer varre o cache local ml_orders.json de cada vendedor em escopo (JsonDatabase::forUser) — não existe listagem nativa do ML filtrada por logística. Mantém só pedidos elegíveis: logistic_type self_service/flex OU tag 'turbo'.
classifica
bucketOf deriva a etapa logística de shipping.status/substatus: delivered=entregue; not_delivered/cancelled/returned ou substatus lost/damaged/stale/delayed=problema; shipped/in_transit/out_for_delivery=a caminho; resto (ready_to_ship/handling/pending/vazio)=a despachar. isTurbo lê a tag ML 'turbo' (NÃO o badge Uber Direct do admin).
metrifica
Calcula contagens por bucket, total, Flex vs Turbo, receita (exclui cancelados) e KPIs de hoje. Ordena por data efetiva desc usando date_closed quando paid/shipped/delivered, senão date_created (regra KPI Rally). Limita a 200 pedidos.
etiqueta
Botão 'Etiqueta' deep-linka para /gc/ml/etiqueta?ids={shipment_id} (PainelMlProxyController::shippingLabel reaproveitado) — só renderiza para buckets a_despachar/em_transito com shipment_id presente. Nenhuma etiqueta é gerada pelo painel em si.
transportadores
Aba carriers(): sem seller_id mostra overview dos vendedores (UserLogManagerService::forView=conectado/mascarado/último OK + CarrierLink::countActive). Com seller_id mostra detalhe + CarrierLink::active + LogManagerLog::recent(60) (trilha ao vivo, read-only). Casa carrier_id contra CarrierDirectory para o selo LogManager.
🌐 Vai pro Mercado Livre / Pix
Nenhuma chamada ML direta nesta tela para listar — os pedidos vêm do cache local ml_orders.json (populado pela sincronia ML em background: webhook + cron).GET /shipments/{id}/labels — disparado apenas ao clicar 'Etiqueta', via deep-link para o proxy existente /gc/ml/etiqueta (PainelMlProxyController), que usa token OAuth fresco do vendedor dono do envio.
⚠️ AtençãoLista alimentada pelo cache ml_orders: pedido recém-pago/recém-despachado só aparece (ou muda de bucket) após a próxima sincronia ML. Forçar sync se o painel parecer atrasado em relação ao Mercado Livre.Classificação depende de logistic_type (self_service/flex) e da tag 'turbo' em shipping.tags estarem no pedido sincronizado — se a sincronia não trouxe esses campos, o pedido não conta como Flex/Turbo e some da lista. Turbo aqui é a tag ML, não o badge Uber Direct do /admin.Botão 'Etiqueta' só aparece com shipment_id e bucket a_despachar/em_transito; entregues e problemas mostram '—'. Sem o token LogManager do vendedor conectado, o rastreio básico funciona mas o fluxo same-day/etiqueta fica limitado — o card de detalhe orienta o gerente a pedir ao vendedor para conectar em painel → Integrações → LogManager.
Crescimento
65

Broadcast (Gerente)

O gerente de contas dispara um comunicado em massa (push APK + Web/PWA + WhatsApp opcional) para TODOS os vendedores vinculados a ele, com preview de quantos alvos receberão antes de enviar e histórico dos broadcasts anteriores.

gc.dominio.com.br/broadcastgc.dominio.com.br/broadcast/preview (POST AJAX)gc.dominio.com.br/broadcast/create (POST)
👤 Você faz e vê
1No menu lateral, abre o grupo 'Crescimento' e clica em 'Broadcast' (ícone avião de papel). A tela tem dois cards lado a lado: formulário à esquerda, histórico à direita com badge de quantos broadcasts já existem.
2Preenche Título (máx 60 caracteres, contador ao vivo) e Mensagem (máx 200 caracteres, contador ao vivo) — ambos obrigatórios.
3Define a URL de destino do clique (padrão /painel/dashboard) e o Tipo: Marketing (respeita opt-out LGPD), Transacional ou Sistema (ignoram opt-out).
4Marca os canais: APK Android e Web/PWA vêm marcados por padrão; WhatsApp é opt-in. Opcionalmente agenda data/hora (datetime-local).
5Clica em 'Pré-visualizar' — sem disparar nada, o sistema retorna quantos vendedores vinculados receberão e a quebra por canal (com APK / com Web). O número aparece num alerta azul.
6Clica em 'Enviar' — um confirm() repete o total estimado antes do POST. O broadcast é gravado e aparece no histórico com status; o disparo real (APK/Web/WA/email/Telegram) acontece depois via cron, não na hora do clique.
o sistema reage por baixo
⚙️ O sistema faz
autoriza
Construtor de GCBroadcastController chama Auth::requireRole('admin','gerente') — vendedor/drop tomam 403. Rotas /broadcast* usam AuthMiddleware + RBACMiddleware::roles('admin','gerente').
escopa-vinculados
index() resolve os alvos com Binding::getUserIdsOf($gerenteId, 'gerente') — SÓ os vendedores vinculados àquele gerente. O histórico é filtrado por created_by === gerenteId (admin vê todos).
preview
POST /broadcast/preview (AJAX, valida CSRF) chama BroadcastService::preview com user_ids = vínculos do gerente. Para cada alvo conta FcmToken::countForUser (APK), NotificationPreference::isEnabled web_push e whatsapp. Retorna JSON {total, with_apk, with_web, with_wa} — nenhum envio.
cria
POST /broadcast/create valida CSRF, exige clientIds não-vazio (senão flash 'Nenhum vendedor vinculado'), injeta filter_user_ids = vínculos e chama BroadcastService::create. Grava em storage/json_db/broadcasts.json (global) com status 'pending' (ou 'scheduled' se scheduled_at preenchido) e created_by = gerente.
segmenta
BroadcastService::resolveTargets dá precedência total a filters.user_ids: como o gerente sempre injeta a lista de vínculos, o alvo fica travado nos vendedores dele — os demais filtros (plano/role/ativo_7d) não são expostos no form do gerente.
dispara-assincrono
O envio real ocorre em BroadcastService::dispatch (chamado pelo cron de comunicação), não no clique. Honra killswitch storage/logs/.broadcast_paused, respeita NotificationPreference por canal/usuário, opt-out de marketing (blog_email_optout), cap MAX_WA_PER_RUN=40 com usleep(2s) entre WhatsApps (anti-ban WA3).
registra-stats
Ao despachar, atualiza status para 'sent' + sent_at e grava stats por canal (sent_fcm, sent_web, sent_wa, sent_email, sent_telegram, errors). O histórico na tela mostra Título, status (badge sent/warning), enviados APK, enviados Web e data.
🌐 Vai pro Mercado Livre / Pix
Nenhuma chamada ao Mercado Livre — broadcast é notificação interna do Rally.FCM (Firebase Cloud Messaging) via FcmPushService::sendBroadcast — push para o app Android.Web Push (VAPID) via WebPushService::notifyBroadcast — push no navegador/PWA.WhatsApp via BlipeiApiClient::sendMessage (transactional=true) — só se canal WA marcado e usuário com whatsapp + opt-in.SmtpMailer e TelegramChannelService existem no dispatch (channel_email/channel_telegram), mas o formulário do gerente só expõe APK/Web/WhatsApp.
⚠️ AtençãoBroadcast do gerente SEM agendamento é salvo com status 'pending', mas o cron jobBroadcastScheduled só processa allScheduledDue() (status 'scheduled' com scheduled_at vencido). Resultado: broadcasts 'enviar agora' do GC ficam pendentes sem dispatch automático — só saem se agendados ou disparados por outro caminho. Validar o ciclo de cron antes de prometer entrega imediata.Alvo é travado nos vendedores vinculados (Binding::getUserIdsOf gerente). Sem vínculos, create() bloqueia com 'Nenhum vendedor vinculado' e o preview retorna total=0 — não é bug, é gerente sem carteira.Entrega por canal depende de NotificationPreference por usuário + token: vendedor sem FcmToken não conta em with_apk, sem opt-in WhatsApp não recebe WA, e tipo 'marketing' pula quem tem blog_email_optout. O 'total' do preview é universo de alvos, não garantia de entrega em todos os canais.
Carteira
66

Cupons em Massa

O gerente de contas cria um cupom de desconto idêntico (percentual, valor fixo ou frete grátis) em várias lojas de vendedores vinculados de uma só vez — porém a criação está temporariamente desativada porque o endpoint de cupom usado antes não existe na API do ML.

/cupons /cupons/bulk · clique pra abrir (já logado)
👤 Você faz e vê
1No subdomínio do gerente (gc.), abra o grupo 'Carteira' no menu lateral e clique em 'Cupons em Massa' (ícone de ticket). O cabeçalho mostra um selo com a contagem de lojas vinculadas.
2Escolha o tipo de desconto: 📊 Percentual (%), 💰 Valor fixo (R$) ou 🚚 Frete grátis — o campo de valor aparece conforme a opção (percentual 1–50% ou valor em reais).
3Defina validade e regras: data de início e término (padrão hoje + 30 dias), valor mínimo de compra, máximo de usos e a opção 'Uso único por comprador'.
4Na seção 'Selecionar lojas', marque as contas ML ativas dos vendedores (botões 'Selecionar todas' / 'Limpar'); um contador mostra quantas estão marcadas.
5Clique em 'Criar cupom em N lojas' e confirme o aviso. O botão exibe progresso (Criando X/N...) e há throttle de 3s entre submissões (anti-WAF).
6Veja o painel de Resultado: quantos cupons foram criados e a lista dos que falharam, com o apelido da loja e o motivo do erro.
o sistema reage por baixo
⚙️ O sistema faz
autentica
GCCuponsController@index chama Auth::requireRole('admin','gerente') — aborta 403 se o papel não for gerente ou admin. Pega o gerenteId via Auth::id().
carrega-lojas
Resolve os vendedores vinculados com Binding::getUserIdsOf(gerenteId,'gerente'), busca cada User e suas MarketplaceAccount::byUserAndType(sid,'mercadolivre'), filtra só as com status='active' e descarta vendedores sem conta ativa. Ordena por nome (usort/strcasecmp).
monta-view
Define title 'Cupons em Massa', viewAtiva='gc-cupons', pre-gera csrfField=CSRF::field() e renderiza resources/views/gc/cupons/index.php (form Alpine bulkCouponForm). Se não houver vendedor com conta ML ativa, mostra empty-state em vez do formulário.
valida-entrada
POST /cupons/bulk (bulkCreate) lê JSON do corpo, valida CSRF::validate (token no body ou header X-CSRF-Token) → 403 se inválido; exige 'type' e array 'accounts' não-vazio → 422 caso contrário.
blinda-vinculo
Reconstrói o mapa de contas permitidas a partir dos bindings do gerente (só contas ML ativas dos vendedores vinculados). Cada account_id enviado que não pertença a esse conjunto é marcado como falha 'Conta sem vínculo' (proteção IDOR).
stub-desativado
RDV-FULL-FIX-001 (2026-06-25): a criação real foi DESATIVADA. Para cada conta selecionada o controller NÃO chama o ML — apenas registra falha com 'Cupom em massa temporariamente indisponível'. O antigo POST /coupons era um endpoint inventado que não existe na API do ML.
responde
Devolve JSON { ok, created:[], failed:[...] } com apelido e motivo por conta. A view exibe quantos criados (sempre 0 no estado atual) e a lista de falhas. Nenhum texto cru de erro do ML é vazado na tela.
🌐 Vai pro Mercado Livre / Pix
NENHUMA chamada ao ML acontece no estado atual — a criação está desativada (RDV-FULL-FIX-001). O endpoint POST /coupons usado antes era inventado (não existe na API do ML).Canônico para reimplementar (TODO no código): POST /seller-promotions/promotions (promotion_type=SELLER_COUPON_CAMPAIGN; sub_type=FIXED_AMOUNT|FIXED_PERCENTAGE, só MLB) + vínculo de itens via POST /seller-promotions/promotions/{PROMOTION_ID}/items — sempre com MarketplaceAccount::decryptToken(access_token) antes do Bearer.
⚠️ AtençãoFuncionalidade desativada: a tela renderiza e o formulário funciona, mas TODA submissão volta com falha 'Cupom em massa temporariamente indisponível'. Nenhum cupom é criado de fato até a reimplementação via API de seller-promotions.Cupom de vendedor no ML só existe para o site MLB e via campanha (SELLER_COUPON_CAMPAIGN) — não pelo endpoint /coupons. Reimplementar exige shape de campanha + vínculo de itens, não o payload simples de cupom que a UI sugere.Só aparecem vendedores com pelo menos uma conta ML ativa vinculada ao gerente; lojas sem conta ativa somem da lista. Sem nenhuma, a tela mostra apenas o aviso de 'nenhum vendedor com conta ML ativa vinculado a você'.
67

Evolução dos Anúncios

O gerente de contas acompanha a evolução de score, vendas e visitas dos anúncios da sua carteira ao longo do tempo, comparando anúncios melhorados pela ferramenta Rally contra anúncios sem melhoria (grupo de controle) para provar o impacto — tudo a partir de snapshots diários capturados por cron, sem nenhuma chamada ao Mercado Livre no momento da visualização.

gc.dominio/evolucaogc.dominio/evolucao?days=7|30|90gc.dominio/api/anuncios/{ann_id}/evolution?seller_id=&days=
👤 Você faz e vê
1No painel do gerente, abre o grupo 'Carteira' no menu lateral e clica em 'Evolução dos Anúncios' (ícone de gráfico subindo). A tela só lista anúncios dos vendedores vinculados a esse gerente.
2Escolhe a janela de tempo nos botões do topo: 7 dias, 30 dias ou 90 dias (padrão 30). Trocar o período recarrega a página via ?days= e recalcula tudo.
3Lê os 3 cards do comparativo: 'Anúncios melhorados pela ferramenta' (verde), 'Anúncios sem melhoria (controle)' e 'Impacto estimado da ferramenta' (vendas extras e Δ de score do grupo Rally vs o baseline).
4Percorre a lista 'Top Movers' — os anúncios que mais subiram no período — com foto, título, vendedor, MLB, evolução de score (de X → Y com o delta colorido) e vendas extras (+N). Anúncios tocados pela ferramenta levam o selo 'RALLY' e barra verde à esquerda.
5Se ainda não há dados suficientes (menos de 2 snapshots no período), vê um aviso informando que o sistema captura snapshots diariamente e que deve voltar no dia seguinte.
o sistema reage por baixo
⚙️ O sistema faz
autoriza
GCEvolucaoController@index exige role admin ou gerente (Auth::requireRole) e resolve os vendedores visíveis via Binding::getUserIdsOf(gerenteId, 'gerente') — gerente só enxerga a própria carteira.
janela
Lê ?days e trava entre 7 e 90 dias (max(7, min(90, days))), default 30. Esse período define o cutoff usado em todos os agregados.
top-movers
AnnouncementSnapshotService::topMovers varre announcement_snapshots.json de cada vendedor, exige ≥2 snapshots no período, calcula score_diff e sold_diff (último menos primeiro), descarta quem não subiu e ordena por (score_diff + sold_diff*5). Retorna os 15 maiores.
enriquece
Para cada top mover, busca o anúncio (Announcement::findById) e o vendedor (User::findById) para preencher título, MLB (marketplace_item_id), foto (photos[0]) e nome do vendedor; marca rally_improved a partir de marketplace_data.rally_improved.
comparativo
Reabre os snapshots de todos os vendedores e separa cada anúncio em dois baldes — 'melhorado pela ferramenta' (rally_improved) vs 'controle' — somando contagem, diferença média de score e total de vendas extras de cada grupo.
impacto
Na view, calcula o impacto estimado da ferramenta como a diferença entre o grupo Rally e o baseline (vendas extras e Δ de score), exibido no terceiro card.
captura-cron
A FONTE dos dados é um job diário (jobAnnouncementSnapshots, throttle 23h via stamp .ann_snapshot_last_run) que chama captureAll: para cada anúncio ATIVO de cada usuário grava 1 snapshot/dia (score via calcQuality, preço, visitas/vendas via AnnouncementDiagnosticService, status, rally_improved), idempotente por dia e auto-prune de 90 dias.
api-timeseries
GET /api/anuncios/{ann_id}/evolution retorna JSON com a série temporal de um anúncio (snapshots + deltas first→last), validando visibilidade do seller_id contra os bindings do gerente (403 sem visibilidade, 422 sem ann_id).
🌐 Vai pro Mercado Livre / Pix
NENHUMA chamada ao Mercado Livre nesta tela. Os dados vêm 100% dos snapshots locais (announcement_snapshots.json) capturados pelo cron diário — a página é leitura pura de JSON, sem token ML nem requisição externa em tempo de visualização.
⚠️ AtençãoSem histórico = tela vazia. Precisa de ≥2 snapshots dentro do período para qualquer anúncio aparecer; conta/vendedor recém-vinculado mostra o empty-state ('volte amanhã') até o cron rodar pelo menos 2 dias. Se o cron diário (jobAnnouncementSnapshots) não estiver rodando, a tela nunca enche.Só anúncios ATIVOS entram no snapshot — captureForUser pula status != 'active' e itens sem marketplace_item_id. Anúncio pausado/encerrado some da série e seu histórico para de crescer; nada é capturado retroativamente.O flag has_promo do snapshot usa announcement.original_price, que o ML descontinuou (PUT bloqueado) — esse campo tende a ficar sempre falso/vazio e não deve ser tratado como indicador confiável de promoção. O comparativo Rally×baseline depende inteiramente do flag marketplace_data.rally_improved estar corretamente marcado pela ferramenta de melhoria.
Financeiro & Conta
68

Financeiro do Gerente

O gerente de contas vê em um só painel a saúde financeira da sua carteira de vendedores — assinantes ativos, inadimplentes, MRR e a receita do seu próprio plano (wallet-to-wallet) — e pode atribuir/trocar o plano de qualquer vendedor vinculado direto da tabela.

gc:/financeirogc:/financeiro/atribuir (POST)
👤 Você faz e vê
1No menu lateral, abra o grupo 'Financeiro & Conta' e clique em 'Financeiro' (ícone de gráfico de pizza). A tela só lista vendedores vinculados a você (multi-tenant via bindings).
2Veja os 4 cartões de topo: Assinantes Ativos (planos pagos), Inadimplentes (overdue), MRR Mensal (soma dos planos ativos mensais) e Meus Vendedores (total da carteira).
3Se você tiver um plano próprio de gerente, aparece o bloco roxo 'Receita do meu plano (wallet-to-wallet)': assinantes do seu plano, inadimplentes, MRR e total histórico — com link para 'Gerenciar planos'.
4Na tabela 'Assinaturas e Planos', consulte por vendedor: plano, ciclo, valor, status (badge colorido), próxima cobrança e saldo da carteira. Clique no nome para abrir o usuário no admin.
5Para trocar o plano de um vendedor, clique no lápis na linha dele: abre um dropdown com seletor de plano e de ciclo (Mensal/Trimestral/Semestral/Anual/Vitalício).
6Escolha o plano e o ciclo e clique 'Salvar' — o sistema cancela a assinatura antiga, cria a nova (se não for grátis) e atualiza o plano do usuário, voltando para a tela com mensagem de sucesso.
o sistema reage por baixo
⚙️ O sistema faz
autentica
Auth::requireRole('admin','gerente') — só admin ou gerente acessam; rota protegida por AuthMiddleware + RBACMiddleware (admin/gerente).
escopa
Binding::getUserIdsOf(gerenteId, 'gerente') resolve os vendedores vinculados ao gerente; só esses IDs entram na tela (blindagem multi-tenant).
monta-linhas
Para cada vendedor com role 'cliente', junta User + Plan (via planMap por slug/id) + Subscription (via subMap por user_id) + Wallet::getBalance(uid); ordena por próxima cobrança (mais recente primeiro).
agrega-kpi
Calcula sobre as assinaturas escopadas: totalActive (active e plano != free), totalOverdue (status overdue) e MRR somando price das assinaturas active de ciclo monthly.
agrega-plano-gerente
GerenteSubscription::byGerente + mrrFor (RDV-GERENTE-BILLING-001): conta assinantes ativos/past_due do plano próprio do gerente e o MRR wallet-to-wallet — bloco só renderiza se houver assinaturas.
atribui-plano
POST /financeiro/atribuir valida CSRF e checa que user_id está nos vínculos do gerente (anti-IDOR); cancela Subscription existente, cria nova se plan != free (com price do ciclo e next_billing +1 mês) e faz User::update(plan).
flash
Mensagens de sucesso/erro via $_SESSION['_flash'] (sessão expirada, acesso negado, plano não encontrado, plano atualizado); redireciona de volta para /financeiro. Sem webhook, e-mail ou chamada externa.
⚠️ AtençãoNÃO consome API do Mercado Livre — é 100% JSON DB local (Wallet, Subscription, GerenteSubscription, Plan, User, Binding). Os números refletem o estado interno de billing, não vendas do ML.MRR conta apenas assinaturas com ciclo 'monthly'; planos trimestrais/anuais/vitalícios não entram no número de MRR mensal (subdimensiona a receita real se a carteira tiver ciclos longos).Atribuir plano aqui NÃO cobra nem debita wallet na hora: só cria a Subscription com next_billing +1 mês e troca o plano do usuário — a cobrança efetiva (wallet-to-wallet, past_due 30d → volta a free) é feita pelo cron de billing do GerenteSubscription, não por esta tela.Só lista usuários com role 'cliente' vinculados ao gerente; vendedor sem binding ativo (ou com role diferente) simplesmente não aparece, mesmo que tenha assinatura.
Global Administrador
69

Vendas ao Vivo (Live)

Painel-estádio em tempo real (estilo Shopee Live) que soma o faturamento de HOJE de todos os vendedores, compara com ontem no mesmo horário, e exibe ranking de vendedores, feed das últimas vendas e ticker rotativo de campeões — ideal para projetar numa TV durante campanhas e gerar competição saudável.

/live /live/campeao /live/publico?token={token}/api/live/feed · clique pra abrir (já logado)
👤 Você faz e vê
1No menu lateral (seção Global Administrador), clique em 'Vendas ao Vivo' — abre uma tela cheia escura, sem o layout normal do painel, com badge pulsante 'AO VIVO', relógio e o faturamento gigante do dia no centro.
2Acompanhe o número de faturamento subir em tempo real: o valor faz animação de 'bump' a cada nova venda, com confete e som (botão de mudo no topo), e mostra o delta percentual vs. ontem no mesmo horário.
3Leia os painéis: mini-gráfico SVG de tendência (hoje verde vs. ontem cinza tracejado), KPIs de visitas/pedidos/ticket médio, ranking 'Top Vendedores' com medalhas e feed das 3 últimas vendas com foto, vendedor e horário.
4Use o botão tela cheia (canto superior) para projetar numa TV; o ticker inferior rotaciona campeão do dia, top vendedor, top 10 produtos mais vendidos e última venda.
5Clique no ícone de compartilhar para gerar um LINK PÚBLICO de 30 minutos — copie e envie para alguém ver a tela sem login (ideal para sócios/equipe externa durante a live).
6Clique no ícone de troféu para abrir a tela permanente do 'Campeão do Dia' (/live/campeao) numa aba/TV separada — versão pública e sempre acessível focada no recordista.
o sistema reage por baixo
⚙️ O sistema faz
autoriza-redireciona
GET /live exige role admin (Auth::requireRole). Se gerente ou fornecedor cair na URL do admin (link compartilhado), resolve a role no DB e redireciona para o /live do subdomínio dele (gc ou drop) em vez de 403.
resolve-escopo
resolveUserIds() lista TODOS os usuários não-admin e não-deletados (User::all filtrado) — o admin vê a soma da 'Equipe Rally' inteira; gerente/fornecedor veem só seus vinculados nos seus próprios controllers.
agrega-snapshot
LiveSalesAggregatorService::snapshot lê ml_orders.json de cada shard de usuário, filtra status válidos (paid/confirmed/shipped/delivered), e soma faturamento, pedidos e unidades para HOJE e ONTEM (mesmo recorte de horário) no fuso America/Sao_Paulo.
data-efetiva
Para 'hoje' usa date_closed (data do pagamento) quando o pedido está paid/shipped/delivered, com fallback para date_created — evita o bug de venda paga hoje mas criada ontem cair fora do dia (RDV date_closed).
rankeia
Monta top 5 vendedores por faturamento, item-recorde (mais unidades hoje), top 10 produtos mais vendidos e buckets de faturamento por hora (0-23) hoje vs. ontem para o mini-gráfico de tendência.
cache-30s
O snapshot inteiro é cacheado em arquivo por 30s (chave = md5 dos userIds) para não martelar os shards quando vários navegadores fazem polling do feed simultaneamente; visitas ML têm cache próprio de 5min.
feed-poll
O componente Alpine liveStadium() faz polling de GET /api/live/feed (JSON, Cache-Control: no-store), detecta IDs de vendas novas, dispara confete/som e atualiza o feed; a versão pública usa /api/live/feed/publico?token=XYZ validado por token de 30min em storage/cache/.live_public_tokens.json.
🌐 Vai pro Mercado Livre / Pix
GET /users/{ml_uid}/items_visits/time_window?last=1&unit=day — total de visitas únicas de hoje, agregado por curl_multi paralelo de todas as contas ML ativas (cache 5min). Token descriptografado obrigatório.GET /users/{ml_uid}/items_visits?ids={ids}&date_from={hoje}&date_to={agora} — visitas de hoje POR item das vendas recentes, para exibir contador de visitas em cada card do feed.
⚠️ AtençãoNÃO confundir com 'Lives & Eventos' (/eventos, subdomínio painel) — aquela é o módulo institucional de transmissões/eventos do vendedor; esta /live é o estádio de KPIs de venda em tempo real (admin/gerente/fornecedor).Cache de 30s no snapshot: uma venda recém-paga pode levar até meio minuto para aparecer no placar; e os dados dependem de ml_orders.json já sincronizado — pedidos ainda não sincronizados do ML não entram no faturamento.Link público vale só 30 minutos e a tela do campeão (/live/campeao) é totalmente pública (sem login) — não compartilhar com quem não deveria ver o faturamento agregado da equipe; tokens expirados mostram tela '🔒 Link expirado'.
Começar grátis no Rally →