Synaplan
기업을 위한 오픈소스 AI 플랫폼
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Controle inteligente de estoque para confecção — MVP (v1).
Next.js 16 · React 19 · TypeScript · Tailwind CSS 4 · componentes no estilo shadcn/ui · Supabase (Postgres, Auth, RLS) · Vercel.
Princípio central: ninguém edita o saldo. O estoque é consequência das movimentações (
ESTOQUE ATUAL = ENTRADAS − SAÍDAS), gravadas por funções transacionais no banco. O histórico é imutável; erros são corrigidos com uma nova movimentação de ajuste, nunca apagando ou editando a original.
Requisitos: Node.js 20+ e npm.
npm install
cp .env.example .env.local
| Variável | Onde usar | Observação |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | navegador + servidor | pública |
NEXT_PUBLIC_SUPABASE_ANON_KEY | navegador + servidor | pública (protegida por RLS) |
SUPABASE_SERVICE_ROLE_KEY | somente servidor | secreta. Ignora RLS. Nunca use NEXT_PUBLIC_. Usada pelo painel de Usuários e pelo seed. |
SEED_PASSWORD | só no npm run seed | opcional; se vazio, o seed gera uma senha aleatória |
Nenhum segredo fica no código. .env* está no .gitignore (exceto .env.example).
Execute em ordem no SQL Editor do Supabase (ou com supabase db push se usar a CLI):
supabase/migrations/0001_schema.sql — enums, tabelas, índices, triggers (imutabilidade, guarda de saldo)supabase/migrations/0002_functions.sql — views, auditoria automática, register_movement, correct_movement, resumossupabase/migrations/0003_rls_grants.sql — RLS, policies e privilégiossupabase/migrations/0004_valor_unitario.sql — valor unitário por produto, valor total em estoque (visível só a administradores) e auditoria de exportaçõessupabase/migrations/0005_contagem_inicial.sql — motivo "Contagem inicial" e lançamento em lotesupabase/migrations/0006_ordem_tamanhos.sql — ordena itens por modelo e tamanho (PP, P, M, G, GG, XG, G1…G5) a partir do nomesupabase/migrations/0007_saida_oc_lote.sql — Saída por OC em lote (tudo ou nada) e OC obrigatória em toda saída de quem não é administradorsupabase/migrations/0008_saida_lote_oc_opcional_admin.sql — no lote, a OC é opcional para administrador (com escolha do motivo)supabase/migrations/0009_relatorio_historico.sql — base dos relatórios de saldo (view stock_report: saldo + histórico de movimentações)supabase/migrations/0014_perfil_expedicao.sql — perfil Expedição: vê o estoque e faz SOMENTE saída por OC (sem entrada, saída avulsa, movimentações ou relatórios)supabase/migrations/0013_estoque_baixo.sql — "estoque baixo" = abaixo do mínimo; mínimo padrão 50 (rode também supabase/manutencao/definir_estoque_minimo.sql: 100 para camisetas PV e calças de brim azul/branca, 50 para o resto)supabase/migrations/0012_busca_sem_acento.sql — busca que ignora acentos e maiúsculas (coluna products.busca)supabase/migrations/0011_valor_somente_admin.sql — o valor unitário só é legível por administrador, no nível do banco (products_admin, product_price)supabase/migrations/0010_valores_pendentes.sql — itens "aguardando valor" / "revisar valor" (tela Produtos → Valores pendentes e alerta no dashboard) e limpeza segura de itens nunca movimentadossupabase/setup_completo.sql reúne 0001–0014 num arquivo só (instalação nova, sem dados fictícios).
supabase/seed/01_catalog.sql é um catálogo fictício opcional, só para demonstração.
supabase/manutencao/limpar_dados_demonstracao.sql no SQL Editor.
(supabase/ATUALIZAR_E_LIMPAR.sql = migration 0004 + limpeza, para colar de uma vez.)npm run import:itens -- "C:\caminho
elatório de estoque.xlsx" --simular # só mostra o que faria
npm run import:itens -- "C:\caminho
elatório de estoque.xlsx" # importa
Pode ser repetido: itens novos são criados e nome/valor dos existentes são atualizados (saldo e histórico nunca mudam). 3. Lance as quantidades na tela Contagem inicial (somente administrador): digite as quantidades da tabela e clique em Lançar contagem. Cada item preenchido vira uma entrada com o motivo "Contagem inicial"; o lote é tudo-ou-nada e protegido contra duplicidade; o rascunho fica salvo no aparelho.
Menu Relatórios (administrador): baixa Estoque atual (código, produto, quantidade, valor unitário, valor total com fórmulas, situação e linha de totais) e Movimentações por período. Também traz Estoque dos itens já movimentados (saldo atual de quem já teve ao menos uma movimentação, com opção de incluir zerados), Itens movimentados com saldo abaixo de N (padrão 150, ajustável; só itens com ao menos uma movimentação no histórico) e Peças com maior quantidade em estoque (top 10/20/50/100), ambos com exportação em Excel. Há relatórios por empresa (ORBENK, SEPAT, PROFISER, GLOBALSEG e "sem empresa"; a lista fica em lib/empresas.ts) e o Excel pode sair na versão completa (com valores) ou para operador (só código, nome e quantidade). O operador também acessa Relatórios, sempre sem valores. Cada exportação fica registrada na auditoria.
npm run seed
Cria pela autenticação real do Supabase: 2 administradores e 3 operadores, e ~20 dias de movimentações (entradas de produção/compra e saídas para OCs 18–25) usando a mesma função do banco que o sistema usa — então saldo, “estoque anterior/posterior” e auditoria ficam consistentes. Inclui o caso do enunciado: Jaqueta Operacional Azul G = 30 unidades e OC 22.
admin, estoque e expedicao (o login aceita só o nome; o sistema completa @estoquebia.app internamente).SEED_PASSWORD; se não definida, é gerada e exibida uma única vez no terminal.update public.profiles set role='admin' where email='[email protected]';
(o papel vem sempre da tabela profiles; usuários criados pelo painel já recebem a função escolhida).npm run dev # http://localhost:3000
Testes em tablet: abra http://IP-DO-SEU-PC:3000 na mesma rede. (Em HTTP puro o sistema continua funcionando; a chave
anti-duplicidade usa um fallback quando crypto.randomUUID não está disponível.)
npm run check # typecheck + lint + testes do banco
npm run test:db # só os testes do banco
npm run test:db aplica as migrations em um Postgres local embarcado (PGlite, emulando auth.uid() e os papéis do Supabase) e verifica,
entre outros (57 verificações):
| Cenário da especificação | Resultado esperado |
|---|---|
| T1 entrada de 30 jaquetas | estoque = 30 |
| T2 saída de 10 p/ OC 22 | estoque = 20 |
| T3 saída de 20 p/ OC 22 | estoque = 0 |
| T4 retirar 1 com estoque 0 | bloqueado (ESTOQUE_INSUFICIENTE), saldo inalterado |
| T5 operador consulta auditoria | sem acesso (RLS) |
| T6 admin consulta auditoria | acesso |
| T7 saída p/ OC | registra produto, qtd, OC, usuário, data/hora, estoque anterior/posterior, IP e user-agent |
| T8 excluir/editar movimentação | bloqueado (inclusive para admin e service role — trigger) |
| T9 duas confirmações rápidas (inclusive simultâneas) | uma movimentação |
Também cobre: quantidade 0/negativa, OC obrigatória/inválida, motivo incompatível, produto inexistente/inativo, usuário desativado, edição direta de saldo (bloqueada), correção administrativa, último administrador protegido, operador só enxerga as próprias movimentações.
O que o teste automático não cobre: as telas e a integração com o Supabase real (Auth, PostgREST). Após subir seu projeto, faça um roteiro manual de fumaça: login como operador → entrada → saída para OC → estoque insuficiente → login como admin → Auditoria/OCs/Usuários.
GitHub → Vercel → Supabase:
.gitignore já protege .env*).SUPABASE_SERVICE_ROLE_KEY como Sensitive; não use NEXT_PUBLIC_ nela).npm run seed localmente (apontando para o mesmo projeto Supabase) se quiser os dados de demonstração.O build (npm run build), TypeScript e ESLint passam sem erros.
app/
(auth)/login/ login
(app)/ área autenticada (layout com menu)
page.tsx início: operador = 4 botões grandes; admin → /dashboard
dashboard/ estoque/ entrada/ saida/ movimentacoes/
produtos/ ocs/ usuarios/ auditoria/ acesso-negado/
actions/ Server Actions (movimentos, produtos, usuários, login)
auth/ route handlers: signout, inactive
components/
ui/ Button, Input/Select, Card, Badge, Dialog (estilo shadcn)
shared/ DataTable, Filters, Pagination, ConfirmDialog, badges, estados, AppShell
estoque/ MovementForm, ProductSelector, QuantityInput
movimentacoes/ produtos/ usuarios/
lib/
supabase/ clientes server / admin (service role) / env
auth/session.ts requireUser, requireAdmin
validations/ schemas zod (movimento, produto)
errors.ts constants.ts utils.ts request-meta.ts
services/ consultas (estoque, movimentações, auditoria)
supabase/
migrations/ 0001 schema · 0002 funções · 0003 RLS
seed/ catálogo fictício
scripts/ seed.ts (usuários + histórico) · test-db.ts
proxy.ts renova sessão e bloqueia rotas privadas (Next 16: "proxy" = antigo middleware)
Verificado em três camadas: proxy.ts (otimista) → servidor (requireUser/requireAdmin em cada página e action) → banco (RLS + funções).
Mesmo chamando o Supabase direto com a chave anon, um operador não consegue nada além do permitido.
| Recurso | Administrador | Operador de estoque |
|---|---|---|
| (perfil Expedição: apenas ver o estoque e fazer Saída por OC — nada mais) | ||
| Ver estoque, detalhe do item | ✅ | ✅ |
| Registrar entrada / saída | ✅ | ✅ (toda saída exige o nº da OC) |
| Saída por OC (várias peças de uma vez) | ✅ (OC opcional) | ✅ (OC obrigatória) |
| Saída sem OC (perda, avaria, ajuste) | ✅ | ❌ |
| Movimentações | todas | só as próprias |
| Dashboard, Produtos, OCs | ✅ | ❌ |
| Corrigir movimentação (ajuste) | ✅ | ❌ |
| Usuários (criar, função, desativar, senha) | ✅ | ❌ |
| Auditoria completa | ✅ | ❌ |
| Editar/excluir movimentação ou saldo | ❌ ninguém | ❌ ninguém |
Tentativas de operadores em áreas administrativas são registradas na auditoria (operacao_invalida).
register_movement (Postgres, SECURITY DEFINER) numa única transação: trava a linha do saldo → valida (quantidade > 0, motivo x tipo, OC, produto ativo, usuário ativo, saldo nunca negativo) → atualiza o saldo → grava a movimentação (com snapshots de usuário, estoque anterior/posterior, IP, user-agent) → grava a auditoria. Se algo falhar, nada é gravado.idempotency_key; o banco devolve a mesma movimentação se a chave se repetir (mesmo em requisições simultâneas).UPDATE/DELETE/TRUNCATE em stock_movements e audit_logs, e o saldo só muda dentro das funções.correct_movement (admin) mantém o registro original e cria um ajuste com a diferença (ex.: entrada 50 corrigida para 40 → saída de ajuste de 10).America/Sao_Paulo e não contam ajustes de correção.OC 22, oc-22 e 22 são normalizadas para 22.Sem reconstruir o sistema: stock_balances.quantidade_reservada (físico × reservado × disponível, hoje sempre 0, já exposto como disponivel na view stock_overview);
product_variants.barcode (QR/código de barras); stock_movements.corrige_movement_id/idempotency_key (integrações); camada services/ para relatórios/Excel;
OCs como texto normalizado (podem virar tabela purchase_orders ligada por oc_number).
Limites conhecidos da v1: os formulários de entrada/saída carregam todas as variações ativas de uma vez (ok para alguns milhares; acima disso, trocar por busca no servidor); não há recuperação de senha por e-mail (um administrador redefine em Usuários).
O sistema é um PWA: no Chrome do celular/tablet, abra o endereço do sistema e toque em Instalar app (ou ⋮ → Adicionar à tela inicial). Ele abre em tela cheia, com a logo da Bia, e atualiza sozinho a cada publicação na Vercel.
Gerar o APK (uso interno, sem Play Store):
.zip: o .apk assinado está dentro. Envie o .apk para os aparelhos (WhatsApp, Drive ou cabo) e instale (o Android pede para permitir "instalar apps desconhecidos").public/.well-known/assetlinks.json com o SHA-256 fingerprint da chave (vem no zip, em assetlinks.json).O app precisa de internet (o banco fica no Supabase); sem conexão mostra uma tela de aviso. Nada do sistema fica salvo no aparelho.