DoPampa3D

🔑 Recuperar senha

Informe seu e-mail e enviaremos um link para criar uma nova senha.

Dashboard
DoPampa3D Manager

⚙️ Configuração do Supabase

Cole as credenciais do seu projeto Supabase para conectar o sistema ao banco de dados na nuvem.

🔔 Notificações de Estoque Baixo

Quando algum filamento estiver em nível crítico, o navegador pode te avisar com uma notificação — mesmo se o app estiver em outra aba (mas precisa estar aberto em algum lugar; não funciona com o app fechado). Verificação feita 1x por dia, ao carregar os dados.

💸 Taxas de Marketplace (Shopee / Mercado Livre)

Usadas na aba Análise de Mercado para calcular quanto realmente sobra de um preço anunciado. Estrutura escalonada por faixa de preço, vigente desde a reforma de mar/2026. Essas taxas mudam de tempos em tempos — atualize aqui quando precisar.

🛍️ Shopee — comissão por faixa de preço
Abaixo de R$8
sem taxa fixa (é % do preço)
R$8 – R$79,99
R$80 – R$99,99
R$100 – R$199,99
Acima de R$200
🟡 Mercado Livre

A comissão real varia por categoria (Clássico ~11–14%, Premium ~16–19%). Os valores abaixo são uma média de mercado — confirme a % exata da sua categoria no Seller Center quando puder.

Acima de R$79,99 o ML não cobra custo fixo, mas o frete grátis passa a ser por sua conta — por isso esse campo separado.

💾 Backup Completo dos Dados

Baixa um arquivo .json com tudo o que está no sistema: filamentos, catálogo, clientes, pedidos e dados de expositores (se o módulo estiver ativo). Guarde esse arquivo periodicamente como cópia de segurança, além do que já fica no Supabase.

🏷️ Marca & Documentos

Esses dados aparecem no cabeçalho dos recibos, comprovantes de pedido e relatórios exportados. Ficam salvos neste navegador.

🖼️
Cole o link direto da imagem do Imgur, ou envie um arquivo do seu computador abaixo — o que for preenchido por último vale.

🔐 E-mail do Administrador

Somente este e-mail terá acesso a este painel. Qualquer outro usuário cadastrado no Supabase será bloqueado.

⚠️ Importante: O e-mail é salvo na tabela sistema_config do Supabase. Se ainda não rodou o SQL dos expositores, faça isso primeiro para que essa tabela exista.

🗄️ Criar Tabelas no Supabase

No painel do Supabase, vá em SQL EditorNew query e cole o SQL abaixo. Execute uma vez e as tabelas estarão prontas.

-- 1. Filamentos CREATE TABLE filamentos ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, marca text NOT NULL, cor text NOT NULL, cor_hex text DEFAULT '#ffffff', tipo text NOT NULL DEFAULT 'PLA', peso_total integer NOT NULL DEFAULT 1000, peso_restante integer NOT NULL DEFAULT 1000, preco_kg numeric(10,2) NOT NULL DEFAULT 0, preco_total numeric(10,2) DEFAULT 0, pago_status text DEFAULT 'pendente', alerta_g integer NOT NULL DEFAULT 200, ativo boolean DEFAULT true, created_at timestamptz DEFAULT now() ); -- 2. Catálogo de produtos CREATE TABLE catalogo ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, nome text NOT NULL, descricao text, foto_url text, tempo_horas numeric(6,2) DEFAULT 0, peso_g numeric(8,2) DEFAULT 0, custo numeric(10,2) DEFAULT 0, preco_venda numeric(10,2) DEFAULT 0, tipo text DEFAULT 'PLA', categoria text, largura numeric(8,2) DEFAULT 0, altura numeric(8,2) DEFAULT 0, profundidade numeric(8,2) DEFAULT 0, filamentos_ids jsonb DEFAULT '[]', ativo boolean DEFAULT true, created_at timestamptz DEFAULT now() ); -- 3. Clientes CREATE TABLE clientes ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, nome text NOT NULL, telefone text, email text, endereco text, cidade text, estado text DEFAULT 'RS', total_gasto numeric(10,2) DEFAULT 0, ativo boolean DEFAULT true, created_at timestamptz DEFAULT now() ); -- 4. Pedidos CREATE TABLE pedidos ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, numero serial, cliente_id uuid REFERENCES clientes(id), cliente_nome text, produto_nome text, catalogo_id uuid REFERENCES catalogo(id), filamento_id uuid REFERENCES filamentos(id), filamento_nome text, filamentos_usados jsonb DEFAULT '[]', quantidade integer DEFAULT 1, peso_total_g numeric(8,2) DEFAULT 0, valor numeric(10,2) DEFAULT 0, desconto numeric(10,2) DEFAULT 0, status text DEFAULT 'feito', pago text DEFAULT 'nao', rastreio text, observacoes text, largura numeric(8,2) DEFAULT 0, altura numeric(8,2) DEFAULT 0, profundidade numeric(8,2) DEFAULT 0, created_at timestamptz DEFAULT now(), updated_at timestamptz DEFAULT now() ); -- 5. RLS: habilitar e liberar acesso total para usuários autenticados ALTER TABLE filamentos ENABLE ROW LEVEL SECURITY; ALTER TABLE catalogo ENABLE ROW LEVEL SECURITY; ALTER TABLE clientes ENABLE ROW LEVEL SECURITY; ALTER TABLE pedidos ENABLE ROW LEVEL SECURITY; -- Policies: qualquer usuário autenticado pode ler e escrever CREATE POLICY "acesso_autenticado" ON filamentos FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON catalogo FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON clientes FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON pedidos FOR ALL TO authenticated USING (true) WITH CHECK (true);

🔧 Migração / Correção de Erros

Se você já criou as tabelas e está recebendo erros como "violates row-level security policy" ou "column not found in schema cache", execute este SQL no Supabase → SQL Editor para corrigir tudo de uma vez:

-- ══ MIGRAÇÃO COMPLETA ══ -- Execute no Supabase → SQL Editor -- Seguro para rodar mesmo se as colunas já existirem -- 1. Adicionar colunas que possam estar faltando em filamentos ALTER TABLE filamentos ADD COLUMN IF NOT EXISTS pago_status text DEFAULT 'pendente'; ALTER TABLE filamentos ADD COLUMN IF NOT EXISTS preco_total numeric(10,2) DEFAULT 0; ALTER TABLE filamentos ADD COLUMN IF NOT EXISTS cor_hex text DEFAULT '#ffffff'; ALTER TABLE filamentos ADD COLUMN IF NOT EXISTS alerta_g integer NOT NULL DEFAULT 200; ALTER TABLE filamentos ADD COLUMN IF NOT EXISTS ativo boolean DEFAULT true; -- 2. Adicionar colunas que possam estar faltando em catalogo ALTER TABLE catalogo ADD COLUMN IF NOT EXISTS filamentos_ids jsonb DEFAULT '[]'; ALTER TABLE catalogo ADD COLUMN IF NOT EXISTS foto_url text; ALTER TABLE catalogo ADD COLUMN IF NOT EXISTS largura numeric(8,2) DEFAULT 0; ALTER TABLE catalogo ADD COLUMN IF NOT EXISTS altura numeric(8,2) DEFAULT 0; ALTER TABLE catalogo ADD COLUMN IF NOT EXISTS profundidade numeric(8,2) DEFAULT 0; ALTER TABLE catalogo ADD COLUMN IF NOT EXISTS ativo boolean DEFAULT true; ALTER TABLE catalogo ADD COLUMN IF NOT EXISTS categoria text; -- 3. Adicionar colunas que possam estar faltando em pedidos ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS catalogo_id uuid REFERENCES catalogo(id); ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS filamento_id uuid REFERENCES filamentos(id); ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS filamento_nome text; ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS filamentos_usados jsonb DEFAULT '[]'; ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS rastreio text; ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS observacoes text; ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS largura numeric(8,2) DEFAULT 0; ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS altura numeric(8,2) DEFAULT 0; ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS profundidade numeric(8,2) DEFAULT 0; ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS updated_at timestamptz DEFAULT now(); -- 4. Adicionar colunas que possam estar faltando em clientes ALTER TABLE clientes ADD COLUMN IF NOT EXISTS total_gasto numeric(10,2) DEFAULT 0; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS ativo boolean DEFAULT true; -- 4b. Desconto por pedido ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS desconto numeric(10,2) DEFAULT 0; ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS custo_material numeric(10,2); -- 4c. Termos de recebimento em consignação (faltava esta tabela) CREATE TABLE IF NOT EXISTS expositor_recebimentos ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), expositor_id UUID REFERENCES expositores(id) ON DELETE CASCADE, itens JSONB DEFAULT '[]', status TEXT DEFAULT 'pendente', criado_em TIMESTAMPTZ DEFAULT now(), aceito_por_nome TEXT, aceito_em TIMESTAMPTZ ); ALTER TABLE expositor_recebimentos ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS "acesso_autenticado" ON expositor_recebimentos; CREATE POLICY "acesso_autenticado" ON expositor_recebimentos FOR ALL TO authenticated USING (true) WITH CHECK (true); -- 5. Corrigir RLS — habilitar e criar policies para usuários autenticados ALTER TABLE filamentos ENABLE ROW LEVEL SECURITY; ALTER TABLE catalogo ENABLE ROW LEVEL SECURITY; ALTER TABLE clientes ENABLE ROW LEVEL SECURITY; ALTER TABLE pedidos ENABLE ROW LEVEL SECURITY; -- Remover policies antigas se existirem (evita erro de duplicata) DROP POLICY IF EXISTS "acesso_autenticado" ON filamentos; DROP POLICY IF EXISTS "acesso_autenticado" ON catalogo; DROP POLICY IF EXISTS "acesso_autenticado" ON clientes; DROP POLICY IF EXISTS "acesso_autenticado" ON pedidos; -- Criar policies novas CREATE POLICY "acesso_autenticado" ON filamentos FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON catalogo FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON clientes FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON pedidos FOR ALL TO authenticated USING (true) WITH CHECK (true);

🏪 SQL — Módulo Expositores

Se você ainda não criou as tabelas de expositores, rode este SQL no Supabase → SQL Editor. Substitua SEU_EMAIL@AQUI.COM pelo seu e-mail antes de executar.

-- 1. Tabela de expositores (lojas parceiras) CREATE TABLE IF NOT EXISTS expositores ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, nome_loja TEXT NOT NULL, responsavel TEXT, telefone TEXT, endereco TEXT, email_acesso TEXT, ativo BOOLEAN DEFAULT true, created_at TIMESTAMPTZ DEFAULT now() ); -- 2. Estoque vinculado a cada expositor CREATE TABLE IF NOT EXISTS expositor_estoque ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), expositor_id UUID REFERENCES expositores(id) ON DELETE CASCADE, catalogo_id UUID REFERENCES catalogo(id) ON DELETE CASCADE, quantidade_inicial INTEGER DEFAULT 0, quantidade_atual INTEGER DEFAULT 0, preco_venda NUMERIC(10,2) DEFAULT 0, created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); -- 3. Histórico de movimentações (com campos extras para venda) CREATE TABLE IF NOT EXISTS expositor_movimentacoes ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), expositor_id UUID REFERENCES expositores(id) ON DELETE CASCADE, estoque_id UUID REFERENCES expositor_estoque(id) ON DELETE CASCADE, tipo TEXT CHECK (tipo IN ('saida','entrada','ajuste','venda','cancelado')) NOT NULL, quantidade INTEGER NOT NULL, observacao TEXT, cliente_nome TEXT, status_pagamento TEXT, valor_total NUMERIC(10,2) DEFAULT 0, desconto_aplicado NUMERIC(10,2) DEFAULT 0, created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); -- 4. Configurações do sistema (admin_email e outras) CREATE TABLE IF NOT EXISTS sistema_config ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), chave TEXT UNIQUE NOT NULL, valor TEXT, updated_at TIMESTAMPTZ DEFAULT now() ); -- Inserir registro do e-mail admin (substitua pelo seu e-mail real) INSERT INTO sistema_config (chave, valor) VALUES ('admin_email', 'SEU_EMAIL@AQUI.COM') ON CONFLICT (chave) DO NOTHING; -- 5. RLS — acesso total para usuários autenticados (admin gerencia tudo) ALTER TABLE expositores ENABLE ROW LEVEL SECURITY; ALTER TABLE expositor_estoque ENABLE ROW LEVEL SECURITY; ALTER TABLE expositor_movimentacoes ENABLE ROW LEVEL SECURITY; ALTER TABLE sistema_config ENABLE ROW LEVEL SECURITY; -- Remover policies antigas se existirem (evita erro de duplicata) DROP POLICY IF EXISTS "expositor_own" ON expositores; DROP POLICY IF EXISTS "estoque_own" ON expositor_estoque; DROP POLICY IF EXISTS "movimentacao_own" ON expositor_movimentacoes; DROP POLICY IF EXISTS "admin_expositores" ON expositores; DROP POLICY IF EXISTS "admin_estoque" ON expositor_estoque; DROP POLICY IF EXISTS "admin_movimentacoes" ON expositor_movimentacoes; DROP POLICY IF EXISTS "acesso_autenticado" ON expositores; DROP POLICY IF EXISTS "acesso_autenticado" ON expositor_estoque; DROP POLICY IF EXISTS "acesso_autenticado" ON expositor_movimentacoes; DROP POLICY IF EXISTS "acesso_autenticado" ON sistema_config; -- Policies: qualquer usuário autenticado pode ler e escrever CREATE POLICY "acesso_autenticado" ON expositores FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON expositor_estoque FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON expositor_movimentacoes FOR ALL TO authenticated USING (true) WITH CHECK (true); -- sistema_config: qualquer autenticado lê, mas só o admin (verificado no app) escreve CREATE POLICY "acesso_autenticado" ON sistema_config FOR ALL TO authenticated USING (true) WITH CHECK (true);

💰 SQL Financeiro Extra (sincroniza entre dispositivos)

Execute no Supabase → SQL Editor para criar as tabelas de Retiradas Pessoais, Pagamentos Avulsos e Despesas de Equipamento. Sem isso, esses registros ficam salvos só neste navegador.

-- 1. Retiradas para conta pessoal (Nubank) CREATE TABLE IF NOT EXISTS retiradas_pessoais ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, valor numeric(10,2) NOT NULL DEFAULT 0, data date DEFAULT CURRENT_DATE, observacao text, created_at timestamptz DEFAULT now() ); -- 2. Pagamentos avulsos de dívidas (filamento ou geral) CREATE TABLE IF NOT EXISTS pagamentos_avulsos ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, filamento_id uuid REFERENCES filamentos(id), filamento_nome text, descricao text, valor numeric(10,2) NOT NULL DEFAULT 0, data date DEFAULT CURRENT_DATE, created_at timestamptz DEFAULT now() ); -- 3. Despesas de equipamento (impressora, ferramentas, manutenção) CREATE TABLE IF NOT EXISTS despesas_equipamento ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, descricao text NOT NULL, valor numeric(10,2) NOT NULL DEFAULT 0, data date DEFAULT CURRENT_DATE, created_at timestamptz DEFAULT now() ); -- 4. RLS: habilitar e liberar acesso total para usuários autenticados ALTER TABLE retiradas_pessoais ENABLE ROW LEVEL SECURITY; ALTER TABLE pagamentos_avulsos ENABLE ROW LEVEL SECURITY; ALTER TABLE despesas_equipamento ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS "acesso_autenticado" ON retiradas_pessoais; DROP POLICY IF EXISTS "acesso_autenticado" ON pagamentos_avulsos; DROP POLICY IF EXISTS "acesso_autenticado" ON despesas_equipamento; CREATE POLICY "acesso_autenticado" ON retiradas_pessoais FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON pagamentos_avulsos FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON despesas_equipamento FOR ALL TO authenticated USING (true) WITH CHECK (true);

🔎 SQL Análise de Mercado

Execute no Supabase → SQL Editor para criar a tabela do histórico de análises e das taxas de marketplace (Shopee/Mercado Livre).

-- 1. Histórico de análises de mercado CREATE TABLE IF NOT EXISTS analises_mercado ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, catalogo_id uuid REFERENCES catalogo(id), nome_produto text NOT NULL, link text, marketplace text DEFAULT 'nenhum', ml_modalidade text DEFAULT 'classico', preco_concorrente numeric(10,2) NOT NULL DEFAULT 0, meu_custo numeric(10,2) NOT NULL DEFAULT 0, meu_preco_venda numeric(10,2) DEFAULT 0, data date DEFAULT CURRENT_DATE, observacao text, created_at timestamptz DEFAULT now() ); -- 2. Taxas de marketplace (linha única, configurável) — faixas Shopee/ML vigentes desde mar/2026 CREATE TABLE IF NOT EXISTS taxas_marketplace ( id int PRIMARY KEY DEFAULT 1, -- Shopee: comissão escalonada por faixa de preço shopee_pct_f1 numeric(5,2) DEFAULT 50, -- < R$8 (sem taxa fixa) shopee_pct_f2 numeric(5,2) DEFAULT 20, -- R$8 – R$79,99 shopee_fixa_f2 numeric(10,2) DEFAULT 4, shopee_pct_f3 numeric(5,2) DEFAULT 14, -- R$80 – R$99,99 shopee_fixa_f3 numeric(10,2) DEFAULT 16, shopee_pct_f4 numeric(5,2) DEFAULT 14, -- R$100 – R$199,99 shopee_fixa_f4 numeric(10,2) DEFAULT 20, shopee_pct_f5 numeric(5,2) DEFAULT 14, -- >= R$200 shopee_fixa_f5 numeric(10,2) DEFAULT 26, shopee_taxa_campanha_pct numeric(5,2) DEFAULT 2.5, -- cobrada de todo vendedor shopee_cpf_alto_volume boolean DEFAULT false, -- CPF com +450 pedidos/90 dias shopee_taxa_cpf_extra numeric(10,2) DEFAULT 3, shopee_frete numeric(10,2) DEFAULT 0, -- Mercado Livre: comissão por modalidade + custo fixo estimado até R$79,99 ml_comissao_classico_pct numeric(5,2) DEFAULT 12, ml_comissao_premium_pct numeric(5,2) DEFAULT 17, ml_custo_fixo_baixo numeric(10,2) DEFAULT 5.5, -- até R$20 ml_custo_fixo_alto numeric(10,2) DEFAULT 6.75, -- R$20 – R$79,99 ml_frete numeric(10,2) DEFAULT 0, -- colunas antigas (modelo simples), mantidas por compatibilidade, não são mais usadas shopee_comissao_pct numeric(5,2) DEFAULT 20, shopee_taxa_fixa numeric(10,2) DEFAULT 4, ml_comissao_pct numeric(5,2) DEFAULT 16, ml_taxa_fixa numeric(10,2) DEFAULT 6, updated_at timestamptz DEFAULT now() ); INSERT INTO taxas_marketplace (id) VALUES (1) ON CONFLICT (id) DO NOTHING; -- 2b. Migração: se a tabela já existia com o modelo antigo, isso adiciona as colunas novas sem apagar nada ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_pct_f1 numeric(5,2) DEFAULT 50; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_pct_f2 numeric(5,2) DEFAULT 20; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_fixa_f2 numeric(10,2) DEFAULT 4; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_pct_f3 numeric(5,2) DEFAULT 14; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_fixa_f3 numeric(10,2) DEFAULT 16; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_pct_f4 numeric(5,2) DEFAULT 14; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_fixa_f4 numeric(10,2) DEFAULT 20; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_pct_f5 numeric(5,2) DEFAULT 14; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_fixa_f5 numeric(10,2) DEFAULT 26; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_taxa_campanha_pct numeric(5,2) DEFAULT 2.5; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_cpf_alto_volume boolean DEFAULT false; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS shopee_taxa_cpf_extra numeric(10,2) DEFAULT 3; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS ml_comissao_classico_pct numeric(5,2) DEFAULT 12; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS ml_comissao_premium_pct numeric(5,2) DEFAULT 17; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS ml_custo_fixo_baixo numeric(10,2) DEFAULT 5.5; ALTER TABLE taxas_marketplace ADD COLUMN IF NOT EXISTS ml_custo_fixo_alto numeric(10,2) DEFAULT 6.75; -- 2c. Migração: análises de mercado precisam saber a modalidade do ML (Clássico/Premium) usada ALTER TABLE analises_mercado ADD COLUMN IF NOT EXISTS ml_modalidade text DEFAULT 'classico'; -- 3. RLS ALTER TABLE analises_mercado ENABLE ROW LEVEL SECURITY; ALTER TABLE taxas_marketplace ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS "acesso_autenticado" ON analises_mercado; DROP POLICY IF EXISTS "acesso_autenticado" ON taxas_marketplace; CREATE POLICY "acesso_autenticado" ON analises_mercado FOR ALL TO authenticated USING (true) WITH CHECK (true); CREATE POLICY "acesso_autenticado" ON taxas_marketplace FOR ALL TO authenticated USING (true) WITH CHECK (true);

🔗 Edge Function: Buscar Dados do Link

Opcional. Ativa o botão "🔗 Buscar dados" na Análise de Mercado, que tenta preencher nome e preço automaticamente a partir do link colado. Funciona bem no Mercado Livre; na Shopee normalmente não encontra nada (a página carrega os dados via JavaScript) — nesse caso você continua preenchendo à mão, sem problema.

1
No painel do Supabase, vá em Edge Functions (menu lateral) → Deploy a new function
2
Nome da função: extrair-produto (exatamente assim, com hífen)
3
Cole o código abaixo no editor e clique em Deploy (se já existir uma versão antiga, é só colar por cima e fazer deploy de novo — essa versão traz diagnóstico de erro)
4
Em Edge Functions → extrair-produto → Settings, marque a opção que permite chamadas sem JWT ("Enforce JWT verification" desligado) — ou, se preferir manter ligado, o app já envia sua sessão autenticada automaticamente
// supabase/functions/extrair-produto/index.ts // Edge Function: recebe { url } e tenta extrair nome + preço da página. // Se não conseguir achar nada, devolve informação de diagnóstico (status // HTTP recebido + um trecho do HTML) pra entender se o site bloqueou o // acesso (comum em Shopee/Mercado Livre quando o pedido não vem de um // navegador de pessoa real). import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type", }; function extrairMeta(html, propriedade) { const re1 = new RegExp('<meta[^>]+property=["\']' + propriedade + '["\'][^>]+content=["\']([^"\']+)["\']', "i"); const re2 = new RegExp('<meta[^>]+content=["\']([^"\']+)["\'][^>]+property=["\']' + propriedade + '["\']', "i"); const m = html.match(re1) || html.match(re2); return m ? m[1] : null; } function extrairMetaName(html, nome) { const re1 = new RegExp('<meta[^>]+name=["\']' + nome + '["\'][^>]+content=["\']([^"\']+)["\']', "i"); const re2 = new RegExp('<meta[^>]+content=["\']([^"\']+)["\'][^>]+name=["\']' + nome + '["\']', "i"); const m = html.match(re1) || html.match(re2); return m ? m[1] : null; } serve(async (req) => { if (req.method === "OPTIONS") { return new Response("ok", { headers: corsHeaders }); } try { const { url } = await req.json(); if (!url) throw new Error("URL não informada"); const resposta = await fetch(url, { redirect: "follow", headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "pt-BR,pt;q=0.9,en;q=0.8", }, }); const html = await resposta.text(); const statusRecebido = resposta.status; const urlFinal = resposta.url; let nome = extrairMeta(html, "og:title") || extrairMetaName(html, "twitter:title"); let imagem = extrairMeta(html, "og:image"); let preco = extrairMeta(html, "product:price:amount") || extrairMeta(html, "og:price:amount"); // Tenta achar preço/nome em blocos JSON-LD (schema.org Product/Offer), // comum no Mercado Livre. if (!preco || !nome) { const blocosLd = [...html.matchAll(/<script[^>]+type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/gi)]; for (const bloco of blocosLd) { try { const parsed = JSON.parse(bloco[1]); const itens = Array.isArray(parsed) ? parsed : [parsed]; for (const item of itens) { const offers = item.offers || (item["@graph"] && item["@graph"].find((g) => g.offers)?.offers); if (offers) { preco = preco || offers.price || offers.lowPrice; nome = nome || item.name; const img = item.image; imagem = imagem || (Array.isArray(img) ? img[0] : img); } } } catch (_erro) { // ignora bloco JSON-LD malformado e segue tentando os próximos } } } const achouAlgo = Boolean(nome || preco); // Log no painel (Edge Functions → extrair-produto → Logs) pra facilitar diagnóstico console.log("URL pedida:", url, "| status recebido:", statusRecebido, "| url final:", urlFinal, "| achou nome:", Boolean(nome), "| achou preço:", Boolean(preco)); const resultado = { nome, preco, imagem, ok: achouAlgo }; // Se não achou nada, devolve pistas de diagnóstico (sem quebrar o app — // o front-end só usa isso pra mostrar uma mensagem melhor) if (!achouAlgo) { resultado.debugStatus = statusRecebido; resultado.debugUrlFinal = urlFinal; resultado.debugSnippet = html.slice(0, 300).replace(/\s+/g, " "); } return new Response(JSON.stringify(resultado), { headers: { ...corsHeaders, "Content-Type": "application/json" }, }); } catch (erro) { return new Response(JSON.stringify({ error: erro.message }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" }, }); } });

🚀 Passo a passo

1
Acesse supabase.com e crie uma conta gratuita
2
Crie um novo projeto (guarde a senha do banco)
3
Vá em Project Settings → API e copie a Project URL e a anon public key
4
Cole as credenciais acima e clique em Salvar e Conectar
5
Vá em SQL Editor, cole o SQL acima e clique em Run
6
Pronto! Volte ao Dashboard e comece a usar.
Pedidos (mês)
por data de criação
Faturamento (mês)
por data de criação
Faturamento Total
todos os pedidos já realizados
Clientes
cadastrados
Filamentos
bobinas ativas
💸 A Pagar
investimentos pendentes
⚠️ Alertas de Estoque

Carregando...

🛒 Pedidos Recentes
#ClienteProdutoValorStatus
Carregando...
🧵 Estoque de Filamentos
🧵

Nenhum filamento cadastrado ainda.

🛒 Pedidos
#DataClienteProdutoQtdValorLucroAndamentoPagoRastreio
Carregando...
👤 Clientes
NomeTelefoneCidade/UFPedidosTotalGasto
Carregando...
Total a Pagar
R$ 0,00
filamento + equipamentos pendentes
Filamentos (custo)
R$ 0,00
valor total investido
🛠️ Equipamentos (custo)
R$ 0,00
impressora, ferramentas etc.
Recuperado via Vendas
R$ 0,00
descontado por pedidos
Pago Avulso
R$ 0,00
pagamentos diretos
Saldo Restante
R$ 0,00
ainda a recuperar
🧵 Dívida Já Recuperada
R$ 0,00
custo já coberto pelas vendas
💰 Saldo em Caixa Disponível
R$ 0,00
livre pra retirar, após dívida quitada
💸 Total Retirado
R$ 0,00
já repassado pra conta pessoal
🧵 Investimentos em Filamentos
FilamentoTipoPesoTotalPreço/kgCustoTotalUsado(g)Status
Carregando...
🛠️ Despesas de Equipamento
💡 Registre aqui compras de impressora, ferramentas, manutenção etc. Esse valor entra na mesma dívida geral do filamento (soma no "Total a Pagar") e é recuperado junto com as vendas, até cobrir tudo que foi investido.
DataDescriçãoValor
Nenhuma despesa de equipamento registrada.
🛍️ Sugestão de Recompra

Carregando...

🏆 Produtos Mais Vendidos
por quantidade vendida (exclui cancelados)
#ProdutoUnid. vendidasFaturamentoTicket médio
Carregando...
🔄 Giro de Estoque — quanto ainda dá pra produzir
com o filamento disponível hoje
💡 Calculado apenas para produtos com 1 filamento vinculado, onde a conta é exata (peso do filamento em estoque ÷ peso do produto). Produtos com múltiplos filamentos não entram aqui pois o consumo por filamento não é individualizado.
ProdutoFilamentoEstoque do filamentoUnidades possíveis
Carregando...
🏦 Retiradas para Conta Pessoal (Nubank)
💡 Registre aqui quando você transfere dinheiro da conta da empresa pra sua conta pessoal. Cada retirada desconta do "Saldo em Caixa Disponível" acima.
DataObservação / MotivoValor
Nenhuma retirada registrada.
💳 Pagamentos Avulsos de Dívidas
💡 Registre aqui pagamentos em dinheiro feitos para abater dívidas de filamentos. O saldo devedor geral é quitado pela soma de: pedidos marcados como "Pago" + estes pagamentos avulsos, até cobrir o custo total investido em filamento.
DataFilamentoDescrição / ContaValor
Nenhum pagamento avulso registrado.
Total Faturado
R$ 0,00
todos os pedidos ativos
Total Recebido
R$ 0,00
pedidos marcados como pagos
A Receber
R$ 0,00
pedidos ainda não pagos
Mês Atual
R$ 0,00
faturado este mês
💎 Lucro Real (total)
R$ 0,00
vendas − custo de produção
💎 Lucro Real (mês atual)
R$ 0,00
apenas pedidos deste mês
🏭 Custo de Produção (total)
R$ 0,00
estimado via catálogo/filamentos
📈 Margem Média
0%
lucro ÷ faturamento
📊 Faturamento por Mês
Mês/AnoPedidosFaturadoRecebidoLucroPendente% Recebido
Carregando...
📦 Pedidos e Pagamentos
#DataClienteProdutoQtdValorLucroAndamentoPago?Ações
Carregando...
⚡ Predefinições salvas
🧵
Filamento
Dados do rolo e do fatiador
R$/kg
g
g
Impressão multicolor (AMS / troca de filamento)
Impressão
Tempo e consumo de energia
h
min
W
R$/kWh
⚙️
Máquina e Consumíveis
Depreciação e desgaste — salvo automaticamente
R$
h
R$
h
Incluir desgaste da cama (PEI)
R$
h
📦
Embalagem e Envio
Custos de materiais de embalagem por pedido
Incluir custos de embalagem no cálculo
🗂️
Objetos na Mesa
Múltiplos modelos diferentes na mesma impressão
Impressão com múltiplos objetos diferentes
Modo atual: peça única ou lote idêntico. Use os campos de Filamento acima e Quantidade abaixo.
📊
Falhas e Preço de Venda
%
un
%
🏪
Taxas de Plataforma e Frete
Descontadas do preço de venda — salvo automaticamente
Incluir custo de frete no cálculo
🏪 Lojas Parceiras
LojaResponsávelTelefoneEndereçoStatusTermosCriado em
Carregando...
🔎 Compare o preço de um produto no Shopee/Mercado Livre com o seu custo e preço de venda. O cálculo já desconta as taxas reais do marketplace (comissão escalonada por faixa de preço + taxa fixa + campanha/frete), configuráveis em Configuração → Taxas de Marketplace.
Análises Feitas
0
no histórico
🟢 Valem a Pena
0
margem real positiva
🔴 Não Valem
0
prejuízo após taxas
🔎 Histórico de Análises
DataProdutoMarketplacePreço ConcorrenteLíquido (após taxas)Meu CustoMargem RealMeu PreçoCompetitividade
Nenhuma análise registrada ainda.