Resumo executivo
Indicadores de decisão do mês corrente — fluxo de saída, prazo, qualidade do atendimento e saúde do estoque. Análise detalhada em Indicadores.
Unidades que saíram · dia (14 dias)
Unidades que entraram · dia (14 dias)
Painel operacional
—
Indicadores de separação
—
Mapa de calor — endereços mais visitados na separação
Cor mais quente = mais bipagens de separação no período. Use para reendereçar os itens de maior giro para perto da doca de expedição e reduzir deslocamento.
| Endereço | Bipagens | Unidades separadas | Pedidos | Item mais separado ali |
|---|
Produtos mais separados
Ranking por unidades separadas no período — candidatos a endereços de maior acessibilidade.
| # | Código | Descrição | Unidades separadas | Pedidos | Endereço mais usado |
|---|
Notas aguardando chegada
Toda nota fiscal criada na aba Recebimento começa aqui. Clique em Receber para registrar quem recebeu, o horário de chegada e a volumetria — a nota só passa a aparecer em Recebimento (pronta para conferência) depois disso.
| NF | Fornecedor | Emissão | Itens | Un. |
|---|
Notas fiscais de entrada
Nova nota
Itens da nota
Importar notas
Notas no Supabase
Usa a conexão configurada na aba NF de Saída (URL e chave anon).
Não configurado.
| NF | Fornecedor | Emissão | Itens | Un. | Status |
|---|
Liberação de validade — recebimento de compra
Itens recebidos com validade abaixo do padrão da saída ficam PENDENTES DE LIBERAÇÃO e NÃO entram em estoque disponível. Não há recusa automática — só o perfil de Compras libera ou recusa, caso a caso, com justificativa.
| Documento | Código | Descrição | Lote | Validade | % vida útil | Qtd | Recebido por | Status |
|---|
Armazenar produto
Três passos: 1) bipe o código do produto · 2) informe a quantidade · 3) bipe o código da localização e conclua. A câmera aceita os dois códigos — o app identifica sozinho se é produto ou endereço.
Entrada manual / leitor pistola
A armazenar
Alimentado pelas conferências de recebimento finalizadas. Clique em usar para preencher os três passos de uma vez.
| Código | Descrição | Lote | Val. | Origem | Documento | Pendente |
|---|
Armazenagens de hoje
| Hora | Código | Lote | Qtd | De | Para |
|---|
Ressuprimento da face de picking
Produtos cuja face de picking ficou abaixo do mínimo. Repor mantém o separador pegando sempre na mesma posição, baixa e perto — sem subir nível nem procurar o lote. A origem sugerida é sempre o lote que vence antes (FEFO), então repor não quebra a regra de saída.
| Código | Descrição | Curva | Face | Na face | Mín/Máx | Repor | Puxar de | Lote (FEFO) |
|---|
A reposição é executada na aba Transferência — o botão repor já leva origem, produto, lote, quantidade e destino preenchidos, passando por todas as validações normais (temperatura, saldo reservado, saldo negativo).
Transferir produto de endereço
Quatro passos: 1) bipe o endereço de origem · 2) bipe o produto/lote · 3) informe a quantidade · 4) bipe o endereço de destino e conclua. A câmera aceita todos os códigos — o app identifica sozinho se é endereço, produto ou caixa fechada.
Entrada manual / leitor pistola
Transferências recentes
| Data/hora | Código | Lote | Qtd | De → Para | Motivo | Usuário |
|---|
Devoluções
Retorno de produto do cliente — avaria de transporte, recusa, recall/não conformidade, vencimento ou erro de expedição. Cada item recebido é triado na hora: volta ao estoque vendável, entra em quarentena ou é descartado.
Nova devolução
| Número | Pedido | Cliente | Motivo | Data | Itens | Status |
|---|
Decisão de qualidade — devoluções bloqueadas
Cada item devolvido entra bloqueado. Só o perfil de Qualidade decide: liberar (volta ao estoque disponível, com endereço), manter em quarentena para análise, ou descartar. A decisão exige motivo tipificado + campo livre e fica registrada com o responsável.
| Devolução | Código | Descrição | Lote | Val. | Qtd | Status |
|---|
Área bloqueada e descarte
Lotes bloqueados por vencimento automático, quarentena de devolução ou bloqueio manual. Item bloqueado nunca aparece na sugestão de separação. Gere a lista de recolhimento para a empresa terceirizada e registre a baixa.
| Código | Descrição | Lote | Validade | Qtd | Endereço | Motivo do bloqueio | Desde |
|---|
Descartes registrados
Baixas de descarte já registradas — pela área bloqueada ou por decisão de qualidade sobre devoluções.
| Data | Código | Lote | Qtd | Motivo | Responsável | Lista |
|---|
Fila de NF de Saída
Nova NF de Saída
Itens da NF
Importar do ERP
validade_min (opcional): validade mínima aceita pelo cliente — 90d = 90 dias até vencer, 40% = 40% da vida útil. encomenda_lote (opcional): lote de compra dedicada — o item só é separado nesse lote. uf_destino (opcional): sigla do estado de entrega — usado para sugerir a embalagem térmica.
A coluna local é opcional: em branco, o app busca o endereço no inventário pela regra FEFO.
Sincronizar com Supabase
Opcional. Com isso a fila de NF de Saída passa a ser compartilhada entre todos os aparelhos do almoxarifado. Sem configurar, o app funciona 100% local.
Não configurado.
| NF | Cliente | Operação | Itens | Un. | Endereços | Prazo | Status |
|---|
Auditoria de faturamento
Fila dos pedidos de venda LIBERADOS ainda não faturados, com as travas já calculadas pelo ERP (auditoria fiscal, política comercial, crédito, frete, pagamento, saldo, prazo). Em cima disso o WMS checa a validade dos lotes disponíveis (regra da Master: % de vida útil; Órgão Público exige mais de 12 meses) e o risco de devolução comparando com o histórico de venda faturada do cliente.
Alertas de risco não travam — sinalizam para você decidir. Marque cada pedido como OK para faturar, Pendência (com o motivo) ou Faturamento futuro (com a data). A decisão fica registrada e substitui a planilha "Análise de Faturamento".
Fila de separação
NF de Saída aguardando separação. O roteiro é montado na ordem do percurso do armazém (rua → módulo → nível), com o endereço de cada produto vindo do inventário e o lote escolhido por FEFO — vence antes, sai antes.
| NF | Cliente | Itens | Un. | Prazo | Endereços |
|---|
Fila de etiquetas
Layouts de etiqueta
Cada modelo é um tamanho + uma lista de elementos posicionados em mm. Os modelos padrão reproduzem as etiquetas de sempre — edite à vontade, o botão Restaurar padrão volta ao original.
Qual modelo cada tela usa
Montar onda de separação
Separe várias NFs numa caminhada só. Cada NF ocupa uma posição fixa do carrinho — ao bipar o produto, o app diz quantas unidades vão em cada posição. O roteiro é consolidado: um mesmo produto pedido por três notas vira uma parada só.
Ou marque as notas na mão — as duas formas funcionam juntas, e a ordem da marcação define a posição no carrinho.
| Posição | NF | Cliente | Itens | Un. | Prazo | Transportadora |
|---|
Dados da conferência
Leitura
Fica gravada em cada leitura seguinte até você mudar o valor — atualize ao trocar de caixa/isopor.
| Hora | Código | Lote | Qtd | Validade | Temp. °C | Local | Status | Observação |
|---|
Lista esperada
É o gabarito do que a conferência espera encontrar — cada linha tem código, lote, validade e quantidade. Em geral já vem preenchida: ao puxar uma NF de Saída para conferir, ou ao concluir uma separação, os itens entram aqui sozinhos. Também dá para importar um CSV ou adicionar item a item numa janela (ícone do cabeçalho — só admin). O campo Lote em branco aceita qualquer lote.
Ao bipar, cada leitura é comparada com a lista: código que não está nela = NÃO PREVISTO; lote, validade ou quantidade diferentes = divergência. A conferência é cega — a quantidade esperada não aparece durante a bipagem, só ao finalizar. Com a lista vazia, toda leitura cai como NÃO PREVISTO. Limpar lista zera tudo.
| Código | Descrição | Lote | Validade | Esperado | Lido | Status |
|---|
Ocorrências de conferência
Na conferência de expedição, toda divergência precisa de uma ocorrência registrada antes de concluir. A ocorrência não sobrescreve a separação original — o histórico mostra o que foi separado errado.
| Produto | Lote | Esperado | Encontrado | Tipo | Separador | Registrada |
|---|
Encerrar
Use os ícones no topo da tela para finalizar, exportar, imprimir, voltar para separação ou iniciar uma nova conferência.
Tudo é salvo automaticamente neste navegador/dispositivo. Nada é enviado para a internet.
Dados da conferência
Leitura
Fica gravada em cada leitura seguinte até você mudar o valor — atualize ao trocar de caixa/isopor.
| Hora | Código | Lote | Qtd | Validade | Temp. °C | Local | Status | Observação |
|---|
Lista esperada
É o gabarito do que a conferência espera encontrar — cada linha tem código, lote, validade e quantidade. Em geral já vem preenchida: ao abrir a NF de entrada e clicar em Conferir esta nota, os itens da nota entram aqui sozinhos. Também dá para importar um CSV ou adicionar item a item numa janela (ícone do cabeçalho — só admin). O campo Lote em branco aceita qualquer lote.
Ao bipar, cada leitura é comparada com a lista: código que não está nela = NÃO PREVISTO; lote, validade ou quantidade diferentes = divergência. A conferência é cega — a quantidade esperada não aparece durante a bipagem, só ao finalizar. Com a lista vazia, toda leitura cai como NÃO PREVISTO. Limpar lista zera tudo.
| Código | Descrição | Lote | Validade | Esperado | Lido | Status |
|---|
Encerrar
Use os ícones no topo da tela para finalizar, exportar, imprimir ou iniciar uma nova conferência.
Tudo é salvo automaticamente neste navegador/dispositivo. Nada é enviado para a internet.
Prontos para embalar
Conferências de expedição já finalizadas, aguardando embalagem e cubagem para envio.
| Documento | Cliente | Data | Resultado |
|---|
Nova embalagem avulsa
Embalagens
| Documento | Cliente | Volumes | Cubagem (m³) | Peso considerado | Status |
|---|
Prontos para despacho
NF de Saída já embalada, aguardando transporte — informe a transportadora para despachar.
| NF | Cliente | Embalagem | Aguardando desde |
|---|
Despachos
| NF | Cliente | Transportadora | Rastreio | Data | Despachado por | Romaneio |
|---|
Cargas a fechar
Despachos com volumes gerados na Embalagem, aguardando a conferência física na entrega à transportadora. Bipe volume a volume contra o romaneio — a carga só fecha com todos os volumes bipados.
| Romaneio | NF | Cliente | Transportadora | Volumes | Corte |
|---|
Cargas fechadas
| Romaneio | NF | Cliente | Transportadora | Volumes | Fechada por | Horário |
|---|
Etiquetas de volume
Reservar peça para OS
Para o colaborador do SAM retirar peça/produto para manutenção ou validação de equipamento: bipe o código do produto e o endereço, informe a quantidade e reserve para a Ordem de Serviço. A reserva sai do disponível na hora. O número da OS é informado depois, na lista abaixo; a baixa por nota fiscal fica na aba OS Pendentes de fechamento.
Entrada manual / leitor pistola
—
Reservas de OS
| Código | Lote | Endereço | Qtd | Finalidade | Solicitante | Situação |
|---|
OS Pendentes de fechamento
Reservas do SAM que ainda não foram fechadas. Cada OS é baixada por nota fiscal: informe o número da NF para dar baixa no estoque (movimento de saída). Enquanto a NF não é informada, a OS fica pendente e o saldo continua reservado.
| OS | Item | Endereço | Qtd | Finalidade | Solicitante | Situação |
|---|
Cadastro de produtos
Base única de produtos do almoxarifado. Alimenta o autocomplete de todas as telas e permite bipar o código de barras EAN do fabricante — o app converte para o código oficial na conferência, separação e armazenagem. Os indicadores abaixo mostram quantos itens estão com cadastro incompleto (sem periculosidade, sem peso, sem embalagem etc.) — clique num indicador para filtrar só esses itens; clique de novo para limpar.
Novo produto
Temperatura de armazenagem
A condição de armazenamento (Ambiente / Refrigerado / Congelado) é sempre calculada a partir desta faixa — não é possível definir manualmente.
Hierarquia de embalagem
O saldo é sempre guardado na menor unidade. Fator = quantas do nível de baixo cabem em um deste. Só inteiro ≥ 1.
Face de picking
Endereço fixo de onde este produto é separado, com a faixa de reposição. Quando o disponível na face cai abaixo do mínimo, o produto entra na fila de Ressuprimento para ser reposto até o máximo, puxando do pulmão pelo lote que vence antes (FEFO). Deixe em branco se o produto não tem face fixa — aí a separação continua buscando o endereço por FEFO no estoque todo.
Formato da etiqueta do fabricante
Layout de leitura da etiqueta do fabricante deste produto (o formato muda de item para item). Deixe sem campos para usar o leitor genérico — só configure quando a etiqueta vier num layout de largura fixa que o app não separa sozinho. Códigos GS1 (Data Matrix de fábrica) ou com campos separados por espaço/vírgula já são lidos direto e dispensam formato.
Monte a leitura da esquerda pra direita: cada linha consome um número de caracteres da etiqueta (ou "resto", só na última linha).
Imagem do produto
Redimensionada para ~480 px e comprimida (JPEG). Guardada na VPS (Supabase) e em cache neste dispositivo.
Importar produtos
Produtos no Supabase
Usa a conexão configurada na aba NF de Saída (URL e chave anon).
Não configurado.
Ler etiqueta / código de barras
Bipe o código do produto — Data Matrix ou código de barras EAN — da embalagem de fábrica para localizar o item no cadastro. Se o código bater com algum produto, o formulário abre já preenchido para consulta ou correção; se não encontrar, abre em branco com o EAN preenchido para cadastro.
Entrada manual / leitor pistola
Gerar etiqueta —
| Status | Img | EAN / DUN | Código | Descrição | Embalagem | Armazenam. | UM | Marca | Cubagem | Periculos. | Vida |
|---|
Pendências de cadastro
Produtos ativos sem embalagem, faixa de temperatura ou imagem. Sem embalagem, o sistema assume unidade.
| Código | Descrição | Falta |
|---|
Cadastrar localização
Endereço no formato Rua | Módulo | Nível. Cada local recebe um código próprio — bipe o local antes dos produtos para registrar onde a mercadoria foi guardada ou de onde foi retirada.
Geração em lote
Os três campos aceitam letra (A → D, ou até AA, AB…) e número (01 → 12). Se você usar letra na rua e número no módulo, tudo bem — cada campo é independente. As medidas, o tipo de área e o peso suportado preenchidos acima são aplicados a todos os endereços gerados.
Locais cadastrados
| Código | Rua | Módulo | Nível | Setor / observação | Tipo de área | Medidas (C×L×A) | Cubagem | Peso suportado | Ocupação atual |
|---|
Sincronizar locais entre dispositivos
Usa a conexão configurada na aba NF de Saída (URL e chave anon). Teste da fundação de sync genérico (tabela wms_estado).
Não configurado.
Caixas de separação (pick-to-cart)
Etiqueta Data Matrix para colar nas caixas plásticas usadas na separação em onda. Numeração sequencial CX001, CX002… — imprima uma vez, em material sintético (transferência térmica com ribbon resina). Na aba Onda de separação, com a conferência ligada, o operador clica na posição e bipa a caixa; a caixa fica vinculada àquela posição pelo resto da onda.
Etiqueta do local
Cadastro de Embalagem
Tipos de caixa cadastrados uma vez — cada caixa salva já gera o Data Matrix dela, usado no modo "Ler código" do processo de Embalagem e também reconhecido em qualquer outro aparelho, mesmo sem essa caixa cadastrada localmente.
| Código | Descrição | C×L×A (cm) | Peso unit. | Térmica |
|---|
Etiqueta da embalagem
Cadastro de Transportadora
CNPJ, nome reduzido, nome e status — usados na aba Expedição para sugerir a transportadora do despacho.
Usado para calcular o peso cubado dos volumes (Comprimento×Largura×Altura em cm ÷ fator) enviado ao TMS Active OnSupply.
| CNPJ | Nome Red. | Nome | Status | Fator cubagem |
|---|
Sincronização entre dispositivos
Usa a mesma conexão Supabase já configurada no app (aba NF de Saída). Tabela fixa: transportadoras.
Não configurado.
Posição de estoque
| Código | Descrição | Lote | Validade | Situação | Qtd | Local | Temp. |
|---|
Itens em endereço incompatível
Divergência de temperatura entre o produto e a posição onde ele está — para achar o que já estava errado antes do bloqueio entrar em vigor.
| Código | Descrição | Lote | Qtd | Endereço | Exige | Endereço é | Quando |
|---|
Saldo dos itens
O saldo parte do que foi lançado no inventário e é movimentado pelas conferências finalizadas: recebimento soma, expedição subtrai. A Contagem de inventário (varredura por local) gera ajuste próprio; a conferência avulsa tipo Inventário continua sem efeito no saldo.
| Código | Descrição | Lote | Val. | Endereços | Físico | Saldo ERP | Reservado | Disponível | Entradas | Saídas | Último mov. |
|---|
Físico = o que está no endereço · Saldo ERP = o que o Oracle acha que tem daquele lote (comparativo, só leitura) · Reservado = preso por NF de saída em aberto, por reservas para OS do SAM e por reservas de contrato · Disponível = o que entra em um pedido novo.
Reserva de contrato
Comodato ou licitação com programação: separa uma quantidade de um lote/endereço que não entra no disponível para a saída comum. A reserva sai do disponível até ser encerrada ou até vencer a data da reserva.
| Código | Lote | Endereço | Qtd | Tipo | Validade da reserva | Situação |
|---|
Etiquetas dos itens marcados (Saldo)
Extrato de movimentação
| Data | Hora | Tipo | Documento | Cliente/Fornecedor | Código | Lote | Val. | Endereço | Qtd |
|---|
Cada linha nasce de uma conferência finalizada. Somente leituras validadas movimentam saldo — divergências (lote errado, não previsto, vencido) ficam de fora.
Consulta por endereço
Bipe (ou digite) o código do endereço e veja o que está guardado ali agora — lote, validade, quantidade, quanto já está reservado e quanto sobra de disponível. A lista sai em ordem FEFO: o que vence antes aparece primeiro.
| Código | Descrição | Lote | Validade | Qtd | Reservado | Disponível | Situação |
|---|
Conferências finalizadas
| Data | Operação | Documento | Responsável | OK | Falta | Diverg. | Resultado |
|---|
Auditoria — quem fez o quê, e quando
Trilha automática de governança: cada operação relevante (Recebimento/Conferência, Armazenagem, Separação, Contagem de inventário, Pedidos, Produtos, Locais) grava sozinha o usuário logado, o início e o fim. Não é possível apagar — só consultar e exportar.
| Início | Fim | Duração | Usuário | Módulo | Operação | Documento |
|---|
Acompanhamento de NF de Saída
Linha do tempo de cada NF de saída: Separação → Conferência → Embalagem → Aguardando transporte → Despachado. "Aguardando transporte" acende assim que a embalagem conclui, e vira concluído (com o nome da transportadora) quando a NF é despachada na aba Expedição. Clique no ícone de uma etapa para abrir a tela daquele processo já naquela NF.
Acompanhamento de Recebimento
Linha do tempo de cada nota fiscal de entrada: Pré-Recebimento → Recebimento → Conferência → Armazenagem → Nota lançada. Clique no ícone de uma etapa para abrir a tela daquele processo já naquela nota.
Indicadores de produtividade e KPIs
Desempenho, qualidade e ciclo da operação — para decisão da gestão, não fila de trabalho (isso fica no Painel operacional da Início).
Atividade diária
Operações registradas por dia (todos os módulos) no período selecionado.
Produtividade por operador
Separação, conferência (saída e recebimento), armazenagem, embalagem e contagem de inventário concluídas no período, por responsável. Linhas/hora é a métrica padrão de picking — compare operadores por ela, não por unidades/hora (que varia com o tamanho do item). Na armazenagem, o tempo é o tempo ativo: intervalos acima de 30 min entre bipagens contam como pausa.
| Usuário | Módulo | Operações | Linhas | Unidades | Horas | Linhas/hora | Un./hora |
|---|
Reslotting — itens fora da posição da curva
Produtos com curva ABC cadastrada guardados numa posição que não combina com o giro deles: curva A longe do início do percurso ou em nível alto, curva C ocupando as posições boas. Mover estes itens encurta a rota de separação todo dia. Use a aba Transferência para remanejar.
| Código | Descrição | Curva | Está em | Qtd | Deveria estar em | Desencaixe |
|---|
Taxa de erro de separação
taxa = linhas com ocorrência de conferência ÷ total de linhas separadas, no período. Para o time de qualidade cruzar com os chamados do ERP.
Evolução mensal (taxa geral)
Ranking por separador
| Separador | Linhas separadas | Linhas com ocorrência | Taxa de erro |
|---|
Por tipo de ocorrência
| Tipo | Ocorrências |
|---|
Itens que mais geram erro
| Código | Descrição | Ocorrências |
|---|
Ciclo do pedido (tempo médio por etapa)
—
Despacho por transportadora
| Transportadora | Despachos no período |
|---|
Assistente
Leitura da operação em linguagem natural, gerada sob demanda a partir dos indicadores e eventos do próprio WMS. O assistente não altera nada no sistema — as ações sugeridas são só atalhos que você acata ou dispensa.
O que é enviado à IA não inclui CNPJ, e-mail, telefone, preço, margem nem crédito.
—
Ações sugeridas
Nenhum insight gerado ainda.
Fila de retorno ao ERP Analyse
O app gera pendências; o RPA (Power Automate) lê a tabela erp_pendencias no Supabase, executa no ERP e devolve o status. Sem Supabase, use o CSV numa pasta de rede.
Pendências
| Criada | Tipo | Chave de negócio | Status | Tent. | Mensagem | Processada |
|---|
Perfis de acesso
Um perfil define quais abas um usuário pode abrir. Sem nenhum perfil cadastrado, todo mundo continua com acesso completo — a restrição só passa a valer depois que você cria perfis e vincula e-mails a eles abaixo.
Novo perfil
Marque as abas que o perfil pode abrir. Para cada aba marcada, escolha se o perfil pode alterar (uso normal) ou só consultar (vê a tela, os dados e os filtros, mas não grava). O Administrador sempre pode alterar.
Sem a permissão marcada, a ação é bloqueada para o perfil (só Administrador passa). Toda tentativa negada é registrada na Auditoria.
| Nome | Descrição | Abas liberadas |
|---|
Usuários e vínculo de perfil
Vincula o e-mail corporativo (o mesmo do login Microsoft) a um perfil. Quem não estiver nesta lista usa o perfil padrão definido abaixo.
Novo vínculo
| Nome | Perfil |
|---|
Perfil padrão para e-mails não cadastrados
Aplica-se a qualquer e-mail logado que não esteja na lista de vínculos acima. Deixe em "(nenhum)" para não restringir ninguém que não esteja explicitamente cadastrado. O modo de teste local (sem login) nunca é restringido, mesmo com perfis configurados.
Sincronização entre dispositivos
Usa a mesma conexão Supabase já configurada no app (aba NF de Saída). Tabelas fixas: wms_perfis e wms_usuarios.
Não configurado.
O SQL de políticas de segurança exige um JWT válido do Entra em toda leitura/escrita e restringe as tabelas sensíveis (wms_perfis, wms_usuarios, estoque, wms_estado). Rode-o no SQL Editor do Supabase depois de criar as tabelas.
Entrada de mercadoria
Parâmetros do recebimento de compra e da área bloqueada.
Dados da empresa
CNPJ, razão social e Inscrição Estadual da Master Diagnóstica — usados como embarcador/remetente ao enviar romaneios para a Active OnSupply.
Usada junto com o cadastro de Transportadora e a conexão Supabase (aba NF de Saída) para enviar romaneios de despacho à Active OnSupply — ver aba Expedição.
Auditoria de faturamento
Parâmetros da aba Auditoria de faturamento (grupo Faturamento). As views do ERP (erp_ped_faturamento, erp_venda_hist) são criadas pela TI a partir do SQL abaixo. Itens com validade abaixo da regra passam a exigir aprovação (perfil Comercial) antes de liberar o faturamento; essa aprovação também dispensa a aprovação de validade na separação.
Assistente de IA
O assistente gera um insight da operação só quando alguém clica — nada é chamado sozinho. O provedor, a chave e o modelo ficam só no servidor. O pacote enviado não leva CNPJ, e-mail, telefone, preço, margem nem crédito; nome de operador entra (para a leitura de produtividade). O histórico fica 60 dias.
Função: —
Backup de emergência do aparelho
Baixa um arquivo JSON com tudo que está salvo neste dispositivo (todas as chaves mdqr_*). Guarde antes de limpar o cache do navegador ou trocar de aparelho. O import substitui o estado local — use com cuidado.
Manual de Operação
Cada processo do armazém, passo a passo, com o fluxograma do caminho que a mercadoria percorre. A regra de ouro: só o que é bipado e validado mexe no estoque — alerta ignorado vira divergência ou problema com o cliente.
Leitura de código de barras
Fundamento de todos os processos.
O app lê o Data Matrix do fabricante (GTIN, lote, validade, série), a etiqueta interna do app, o código linear (EAN, Code 128, ITF-14) e códigos com campos separados por espaço/vírgula. Com o EAN cadastrado no produto, bipar o código do fabricante já resolve para o código oficial da Master e completa a descrição.
- Leitor USB / pistola: "digita" o código no campo. Se não ler um tipo, habilite a simbologia na folha de configuração do manual do leitor.
- Câmera Android/Chrome: lê tudo (recomendado no celular). iPhone: use o Safari. Navegador de computador sem leitor nativo lê só QR — use o leitor USB.
1 · Pré-Recebimento
Quando: a NF já foi lançada e a carga chegou (ou vai chegar) na doca.
- Abra Pré-Recebimento e a nota. "Recebido por" e "Chegada" já vêm preenchidos — ajuste se preciso.
- Informe a volumetria (volumes / paletes que chegaram) e salve.
- A nota passa a aparecer na Conferência de Recebimento.
2 · Conferência de Recebimento
Quando: conferir fisicamente o que chegou contra a NF — código, lote, validade, quantidade.
- Abra a nota → "Conferir esta nota" — os itens da NF viram a lista esperada.
- Bipe cada item. Só leitura OK soma ao estoque; divergências ficam registradas mas não movimentam saldo.
- Finalizar — a NF vira "Conferida", o saldo recebe a entrada, sobe para o servidor e o item segue para a Armazenagem.
Resultado de cada leitura: OK LOTE DIVERGENTE NÃO PREVISTO EXCEDENTE DUPLICADO / VALIDADE FALTANTE
3 · Liberação de validade (recebimento) — perfil Compras
Quando: um item chegou com vida útil abaixo do mínimo (padrão 75%). Fica PENDENTE DE LIBERAÇÃO, fora do estoque disponível.
- Liberar: escolha o endereço sugerido (temperatura compatível, lote lado a lado) → entra no estoque.
- Recusar: não entra — tratamento com o fornecedor.
4 · Armazenagem
Quando: guardar no endereço o que já foi conferido e está na doca.
- Bipe o produto — o app sugere a quantidade pendente, mostra onde o lote já está e um endereço sugerido.
- Ajuste a quantidade; bipe o endereço e toque em Concluir armazenamento. O endereço continua selecionado para guardar vários itens em sequência.
5 · NF de Saída — a fila de trabalho
Uma NF de saída nasce A separar, vira A conferir quando o separador termina e fecha em Concluído quando a conferência é finalizada. A fila mostra por padrão só o que está em aberto. O botão separar monta o roteiro; conferir carrega os itens e abre a conferência.
6 · Separação
Quando: retirar do estoque os itens de uma NF de saída, pelo roteiro do armazém e regra FEFO (vence antes, sai antes).
- Iniciar separação — o app monta o roteiro (rua → módulo → nível), escolhe o lote por FEFO e reserva o saldo.
- Bipe o endereço → bipe o produto; a linha avança. "tb:" mostra endereços alternativos.
- Sem saldo na posição: botão ruptura + motivo. A conferência passa a esperar só o que realmente saiu.
- Concluir a separação é o que libera a NF para a conferência.
Onda de separação (carrinho)
Quando: há várias notas pequenas na fila. Separa todas numa caminhada só.
- Montar: marque as notas na mão (a ordem da marcação vira a posição no carrinho) ou use Sugerir onda por prazo, transportadora ou cliente. As duas formas funcionam juntas.
- Cada NF ocupa uma posição do carrinho — as caixas plásticas levam etiqueta CX001, CX002… (gerada no card Caixas de separação, aba Locais).
- O roteiro é consolidado: um produto pedido por três notas vira uma parada só.
- Ao bipar o produto, o app diz quantas unidades vão em cada posição. Confirme posição por posição ou use Confirmar tudo.
- Conferência da caixa (opcional): ligue exigir conferência da caixa no card Montar onda. Aí o operador clica na posição e bipa uma caixa CX; ela fica vinculada àquela posição pelo resto da onda e o app recusa a caixa errada. Nesse modo o Confirmar tudo fica oculto.
- Ruptura marca só as posições ainda não atendidas — as outras notas seguem normalmente.
7 · Aprovação de validade (saída) — perfil Comercial
Quando: a NF só pode ser atendida com lote de validade abaixo do que o cliente exige, ou abaixo do limite padrão.
- Aprovar → NF liberada para separação.
- Reprovar → tratamento comercial com o cliente.
8 · Conferência de expedição
Quando: conferir o que o separador retirou, antes de embalar. Conferência cega (não mostra a quantidade esperada).
Finalizar libera a reserva, baixa o estoque e a NF vira Concluída.
9 · Embalagem e cadeia fria
- Monte os volumes escolhendo as caixas padrão — o app calcula cubagem e peso cubado.
- Produto frio: o app mostra a sugestão de embalagem térmica pela UF (SP → parede simples ≥ 48 h; fora de SP → parede dupla ≥ 72 h).
- Para cada volume térmico, toque em "confirmar gelo" depois de colocar o gelo.
- Conclua — cada volume ganha etiqueta com código próprio (Data Matrix) para o fechamento de carga.
10 · Expedição
A transportadora prevista já vem preenchida; o card mostra as últimas usadas por esse cliente. Ao confirmar, os volumes ficam vinculados à NF e ao romaneio.
11 · Fechamento de carga
Quando: entregar a carga para a transportadora, bipando volume a volume contra o romaneio.
- Bipe cada volume. Volume desconhecido ou de outro romaneio é recusado; repetido dá aviso.
- O romaneio só fecha com todos os volumes bipados. Fica registrado quem fechou, a transportadora e a hora.
11b · Reserva para OS (SAM) e fechamento por nota fiscal
Quando: um colaborador do SAM retira uma peça/produto para manutenção ou validação de equipamento, vinculada a uma Ordem de Serviço.
- Na aba Reserva para OS (SAM): bipe o código do produto e o endereço, ajuste a quantidade, escolha a finalidade e o equipamento, e clique em Reservar para OS. Informe o nome de quem está retirando. A peça sai do disponível na hora.
- Quando tiver o número da OS, clique em informar OS na lista. A reserva passa para OS Pendentes de fechamento.
- Na aba OS Pendentes de fechamento, ao emitir a nota fiscal, clique em informar NF. Isso baixa o estoque (movimento de saída) e fecha a OS.
12 · Devolução de cliente
Abra pela nota de devolução ou pelo chamado do ERP. A triagem só registra o item; ao concluir, todos os itens entram BLOQUEADOS em quarentena — saldo visível, indisponível para separação.
13 · Decisão de qualidade — perfil Qualidade
- Liberar → volta ao disponível, escolhendo o endereço.
- Manter → continua em quarentena.
- Descartar → saída + registro de descarte.
Motivo tipificado (produto errado, item faltante, pedido incorreto, avaria, temperatura, validade, outro) + campo livre obrigatórios. Histórico completo por item.
14 · Área bloqueada, vencidos e descarte
- Vencidos — ao virar a validade, o lote é bloqueado automaticamente (1×/dia, na abertura do app) e movido para o endereço da área bloqueada, se configurado. Nunca aparece na separação.
- Recolhimento — em Área bloqueada e descarte, marque os lotes e gere a lista de recolhimento (CSV para a terceirizada).
- Baixa — registre a baixa com o responsável. O saldo é zerado e o movimento fica no extrato.
15 · Inventário — lançamento e contagem
A localização é obrigatória — sem endereço o produto não entra no roteiro de separação. A contagem é cega (o app não mostra o saldo do sistema).
16 · Ajuste de inventário com aprovação — perfil Inventário
- Aprovar → o estoque é ajustado (movimento AJUSTE + CSV contábil).
- Reprovar / recontar → o saldo não muda.
17 · Inventário rotativo
Quando: contar o armazém aos poucos, todo dia, sem parar a operação.
- Defina a curva ABC dos produtos no cadastro e o prazo de cobertura por curva (padrão A 30 / B 60 / C 90 dias) na tela do rotativo.
- Abra Inventário rotativo — contagem do dia — a lista já vem sorteada (curva ABC, giro, valor, urgência de validade, histórico e tempo sem contar).
- Toque em Iniciar — a contagem segue igual à do processo 15.
- Endereço que não dá para contar hoje: reagendar com motivo — volta no próximo sorteio.
- Acompanhe em Cobertura do ciclo o % no prazo por curva e os endereços vencidos.
Ressuprimento da face de picking
Quando: a posição fixa de separação de um produto ficou abaixo do mínimo.
- A face e a faixa mínimo/máximo são cadastradas no produto (aba Produtos → Face de picking).
- A fila mostra quanto tem na face, quanto repor e de onde puxar — sempre o lote que vence antes.
- O botão repor leva tudo preenchido para a Transferência; lá você confere e conclui.
Consulta por endereço
Quando: você está no corredor e precisa saber o que tem numa posição — antes de guardar, de separar ou de contar.
Mostra cada produto/lote com validade, quantidade, quanto está reservado e quanto sobra de disponível, mais a ocupação do endereço em cubagem e peso. Lote vencido aparece como VENCIDO e lote em quarentena como QUARENTENA.
18 · Transferência de localização
Quando: remanejar um produto de um endereço para outro dentro do armazém. Não é entrada nem saída.
Ao bipar a origem, o app lista o que existe ali (botão usar por linha). Origem e destino continuam para mover vários itens; Inverter troca os dois; Mover tudo deste endereço transfere a posição inteira.
Status e alertas — referência rápida
NF de Saída: A separar Separando A conferir Concluído · Contingência (separado no papel).
Nota fiscal: aguardando chegada → A conferir → Conferida.
Leitura: OK LOTE DIVERGENTE NÃO PREVISTO EXCEDENTE DUPLICADO VALIDADE FALTANTE LOCAL DIFERENTE
| Problema | O que fazer |
|---|---|
| "Aguarde 1 segundo" | Você bipou rápido demais. Espere 1 s e bipe de novo — a leitura anterior foi aceita. |
| O código do fabricante não vira o código da Master | O EAN não está cadastrado no produto, ou a etiqueta do fabricante precisa de um formato calibrado no cadastro do produto (seção "Formato da etiqueta do fabricante"). |
| Câmera não abre | A página precisa estar em https://. Em computador sem leitor nativo, use o leitor USB. |
| Endereço bloqueado ao guardar/transferir | Tipo de área incompatível com a temperatura do produto — escolha outro endereço. |
| Botão "Finalizar" da conferência não habilita | Há divergência sem ocorrência registrada. Registre a ocorrência de cada item. |
| Faixa vermelha "armazenamento cheio" | Pare de bipar, toque no selo de sincronização, recarregue a página. |
| NF não aparece na conferência | A separação ainda não foi concluída — é a conclusão que libera a NF. |
| Faixa vermelha "banco responde sem login" | Problema de configuração do servidor — avise a TI. Não é erro seu. |
Contingência e trabalho offline
Sem internet o app continua funcionando — o que você bipa fica no aparelho e sobe sozinho quando a conexão volta. Um aviso no topo mostra o estado da conexão.
Manual de TI
Instalação, configuração, escalabilidade e recuperação. Assume as correções de segurança já aplicadas ao código (CSP, migrações fechadas, tabelas de arquivo imutável, Edge Function com validação de JWT). Acesso restrito ao perfil Administrador.
1 · Arquitetura
Front-end de arquivo único, sem build — não há servidor de aplicação. Persistência local (localStorage, chaves mdqr_*_v1) com espelho no Postgres via Supabase (na prática obrigatório em produção multi-coletor).
| Componente | Onde vive |
|---|---|
wms-master.html + css/wms.css + js/wms-boot.js + js/wms-app.js + sw.js | hospedagem estática HTTPS — wms.masterdiagnostica.com.br |
| Identidade: MSAL.js (CDN Microsoft) + Entra ID (tenant único) | App Registration |
| Banco: Supabase self-hosted (Postgres + PostgREST + GoTrue + Storage + gateway) | VPS Hostinger — supabasemas.masterdiagnostica.com.br |
Integração TMS: Edge Function enviar-romaneio-aos | Supabase Functions (Deno) |
Integração ERP: tabela erp_pendencias consumida por RPA (Power Automate) | Power Automate + service_role |
Sincronização por área: cada área vira 1 linha em wms_estado (blob JSON, lock otimista por versao). Todo fetch ao Supabase leva o access token do Entra no Authorization; a anon key vai só no apikey.
2 · Pré-requisitos de infraestrutura
- Hospedagem estática com HTTPS (a câmera exige
https://). Os 4 arquivos +sw.jsna mesma origem/pasta. - VPS com Supabase self-hosted (Docker): Postgres 15+, PostgREST, GoTrue, Storage, gateway. ≥ 2 vCPU / 4 GB RAM / 40 GB SSD para o porte atual, disco com folga para o crescimento de
wms_estado/wms_historico/ imagens. - Tenant Microsoft 365 com permissão para criar App Registration.
- Power Automate com conector Oracle/Analyse para o RPA.
- Credencial da Active OnSupply (Token de Integração) para o TMS.
- Leitores 2D (leem Data Matrix) + impressora Zebra TLP 2844 (ZPL), etiqueta 50 × 30 mm.
3 · Microsoft Entra ID — App Registration
- New registration — "WMS Master". Account types: single tenant.
- Authentication → Add a platform → Single-page application. Redirect URI:
https://wms.masterdiagnostica.com.br(exato, sem barra final). Marque Access tokens e ID tokens. - Expose an API — Application ID URI
api://<client-id>. Add scopeaccess_as_user(admin+user consent, Enabled). - API permissions — Graph delegadas
openid,profile,email. Grant admin consent. - Anote Application (client) ID e Directory (tenant) ID.
tid em wms_entra_ok() garante que só contas do tenant da Master acessam — barrado no banco, não só na tela.4 · wms-boot.js / WMS_CONFIG
Topo de js/wms-boot.js. Nenhum valor é segredo (client id, tenant id e anon key são públicos por design) — a segurança vem das políticas do banco.
var WMS_CONFIG = {
MSAL_CLIENT_ID: '<Application (client) ID>',
MSAL_TENANT_ID: '<Directory (tenant) ID>',
MSAL_REDIRECT_URI:'https://wms.masterdiagnostica.com.br', // == Redirect URI do Entra
ALLOWED_DOMAIN: 'masterdiagnostica.com.br', // '' desliga a checagem
MSAL_API_SCOPE: 'api://<client-id>/access_as_user', // vazio => usa id_token
TESTE_LOCAL_PERFIL: 'Teste',
TESTE_LOCAL_ADMIN: true, // file://localhost roda como Admin. Produção nunca é teste.
SUPABASE_URL: 'https://supabasemas.masterdiagnostica.com.br',
SUPABASE_ANON_KEY:'<anon key do projeto>'
};
MSAL_REDIRECT_URI | idêntico ao do Entra, senão o login falha (AADSTS50011). |
MSAL_API_SCOPE | preenchido → access token; vazio → id_token. A validação de JWT do Supabase precisa aceitar o aud correspondente. |
TESTE_LOCAL_ADMIN | só afeta file:// e localhost. Em produção login e perfis são sempre obrigatórios. |
5 · Supabase — banco
5.1 Validação de JWT do Entra
É o que faz wms_entra_ok() funcionar (Authentication → Third-Party / JWT, ou a config equivalente do PostgREST no self-hosted):
JWKS URL : https://login.microsoftonline.com/<tenant>/discovery/v2.0/keys Issuer : https://login.microsoftonline.com/<tenant>/v2.0 Audience : <client-id> (ou api://<client-id> , conforme o "aud" do token)
Sem isso, toda chamada autenticada falha — ou, se as políticas inseguras estiverem ativas, o banco fica aberto à anon key. O app tem um diagnóstico: se o banco responde a uma leitura feita só com a anon key, aparece uma faixa vermelha fixa + registro na auditoria.
5.2 Tabelas principais
| Tabela | Papel · SQL gerado por |
|---|---|
pedidos, notas_fiscais, produtos, transportadoras, estoque, produto_imagens | dados operacionais · botão "Baixar SQL da tabela" na aba correspondente |
wms_estado | sync por área (1 linha por area_<nome>, dados jsonb, versao). Guarda também locais e perfis. · aba Locais |
wms_perfis, wms_usuarios | perfis e vínculos e-mail→perfil · aba Configurações |
erp_pendencias | fila para o RPA, unique(tipo, chave_negocio), o app só insere · aba Integrações |
wms_historico, wms_estado_hist | append-only (sem update/delete: política + trigger) · sqlPoliticasSeguras |
5.3 Índices
create index if not exists wms_estado_chave_idx on public.wms_estado (chave); create index if not exists produtos_dun_idx on public.produtos (codigo_dun); create index if not exists wms_historico_area_idx on public.wms_historico (area, arquivado_em); create index if not exists wms_estado_hist_chave_idx on public.wms_estado_hist (chave, snap_em);
6 · Ordem de execução dos scripts SQL
No SQL Editor do Supabase, nesta ordem (todos idempotentes):
- Tabelas base — "Baixar SQL da tabela" de cada aba: NF de Saída, Recebimento, Produtos, Transportadoras, Saldo, Locais (
wms_estado+sqlAreasSync), Configurações, Integrações. migracao_v8.sql(bloco UP) — embalagem, temperatura, imagem, GS1, tabelas opcionais de relatório.migracao_v9_perfil_comercial.sql(bloco UP) — colunapode_comercial.supabase_policies_seguras.sql— botão "Baixar SQL de políticas (segurança)" na aba Configurações. Cria helpers, todas as políticas RLS, as tabelas de arquivo imutável e os triggers. Rode por último e re-rode após qualquer mudança de tabela.- Bootstrap do 1º Administrador — seção 9.
supabase_policies_seguras.sql e rode. Ele é a fonte autoritativa das políticas.7 · Políticas de segurança (RLS)
| Tabelas | Regra |
|---|---|
pedidos, notas_fiscais, produtos, transportadoras, produto_imagens | CRUD para qualquer autenticado do tenant (wms_entra_ok()). |
estoque, wms_estado | select/insert/update para autenticado; DELETE só Administrador. |
wms_perfis, wms_usuarios | leitura para autenticado; escrita só Administrador. |
wms_historico, wms_estado_hist | só select + insert; sem update/delete (RLS + trigger). Imutável. |
Retenção do arquivo (job mensal com service_role — desabilite o trigger antes):
alter table public.wms_historico disable trigger wms_historico_imutavel; delete from public.wms_historico where arquivado_em < now() - interval '5 years'; alter table public.wms_historico enable trigger wms_historico_imutavel;
8 · Edge Function — enviar-romaneio-aos
Proxy para a Active OnSupply. Mantém o token do TMS no servidor e valida o JWT do Entra (JWKS + tid + aud + exp).
supabase secrets set \ ACTIVEONSUPPLY_TOKEN='<Token_Integracao>' \ ACTIVEONSUPPLY_BASE_URL='https://ws.activeonsupply.com.br/API' \ WMS_ENTRA_TENANT_ID='<tenant>' \ WMS_ENTRA_CLIENT_ID='<client-id>' \ WMS_ALLOWED_ORIGIN='https://wms.masterdiagnostica.com.br' # deploy SEM verify_jwt do Supabase (a função faz a própria verificação) supabase functions deploy enviar-romaneio-aos --no-verify-jwt
Homologação: ACTIVEONSUPPLY_BASE_URL = https://homologacao.activeonsupply.com.br/API.
9 · RPA / Power Automate — retorno ao ERP
O app só insere em erp_pendencias (idempotente por tipo + chave_negocio). 6 tipos: conferência de recebimento, volumetria da nota, expedição despachada, ajuste de inventário aprovado, devolução recebida, decisão de qualidade.
- O fluxo lê
erp_pendenciascomstatus in ('pendente','erro')usando aservice_rolekey. - Após processar:
PATCHstatus+processado_em+mensagem_erro. - Alerta "RPA parado" quando há pendências abertas e nada foi processado nas últimas 3 h.
erp_pendencias.10 · Perfis de acesso e bootstrap
- Em Configurações, crie os perfis (Operador, Compras, Comercial, Qualidade, Inventário, Estorno, Administrador) marcando abas e permissões especiais. Para cada aba marcada define-se pode alterar ou só consultar (nesta última o perfil vê a tela e os filtros mas não grava; sincroniza na coluna
abas_mododewms_perfis). - Crie os vínculos e-mail → perfil. Crie ao menos um Administrador.
- Enviar para o Supabase.
- Depois de cadastrar o 1º Administrador, remova as duas policies de bootstrap:
drop policy if exists "wms bootstrap wms_perfis" on public.wms_perfis; drop policy if exists "wms bootstrap wms_usuarios" on public.wms_usuarios;
Defina o perfil padrão para e-mails não cadastrados (Configurações). "(nenhum)" = acesso completo para qualquer login do tenant.
11 · Parâmetros operacionais
| Parâmetro | Onde |
|---|---|
| E-mail do comprador / vida útil mínima (%) / endereço da área bloqueada / endereço de quarentena | Config → Entrada de mercadoria |
| CNPJ, razão social, IE (usados no romaneio ao TMS) | Config → Dados da empresa |
| Corte Correios (15:00) / demais transportadoras (16:00) | aba Fechamento de carga |
| Dias sem carga refrigerada nos Correios (padrão qui/sex) | aba Fechamento de carga |
| Caixas térmicas (parede simples/dupla, autonomia em horas) | Cadastro de Embalagem |
Formato do código de endereço (RUA-00-00) / tamanho da etiqueta de local | aba Locais |
| Prazo de cobertura por curva ABC (A 30 / B 60 / C 90 dias) e pesos do sorteio do inventário rotativo | aba Inventário rotativo |
12 · Impressão — Zebra TLP 2844
No driver ZDesigner TLP 2844 (Preferências de impressão), uma vez:
- Stock personalizado
50,8 mm × 30 mm. Margens 0. - Media type: térmica direta (ou transferência com ribbon). Tracking: Web sensing.
- Velocidade 2–3 ips · darkness 8–12. Rodar a calibração do rolo antes do 1º lote.
Na janela do navegador: destino ZDesigner TLP 2844 · escala 100% (nunca "ajustar à página") · margens nenhuma · desmarcar cabeçalhos e rodapés. Formatos de porta-palete (100×50, 100×35) exigem stock correspondente, orientação retrato.
13 · Service Worker (sw.js)
- Network-first do app; não intercepta o Supabase.
- A variável
CACHEprecisa ser incrementada a cada publicação que mude HTML, CSS ou JS — senão o navegador serve o cache velho. - Publicado na mesma pasta do
wms-master.html. Não registra emfile://.
14 · Rotina de publicação (release)
node tests/run.js— deve passar (233+).- Incrementar
CACHEemsw.js. - Publicar juntos, na mesma origem:
wms-master.html,css/wms.css,js/wms-boot.js,js/wms-app.js,sw.js. - Se algum SQL gerado mudou: rodar
supabase_policies_seguras.sqlde novo. - Se a Edge Function mudou:
supabase functions deploy enviar-romaneio-aos --no-verify-jwt. - Smoke test em produção: login → abrir uma aba → forçar renovação de token (aba aberta ~1 h) → câmera (HTTPS) → selo de sincronização → romaneio de teste.
- Confirmar que o arquivo continua em LF.
wms-master.html (comentário no arquivo) e do Redirect URI. Remover a CSP é seguro e reversível.15 · Escalabilidade
PostgREST
Corta respostas em db-max-rows (default 1000). O app pagina as leituras grandes. Para menos requisições:
# .env do Supabase self-hosted PGRST_DB_MAX_ROWS=5000
Crescimento de wms_estado
Cada área é 1 linha com blob JSON que cresce com os eventos. Tetos no cliente: movimentos 15.000, auditoria 15.000, inventarios 3.000, volumes_carga 30.000. Ao ultrapassar, o excedente vai para wms_historico (imutável) antes de ser cortado do blob — nada é perdido. Snapshot diário das áreas de estado pequenas em wms_estado_hist.
- Monitorar o tamanho de
area_movimentos/area_auditoriae o total dewms_historico. - Job de retenção (seção 7) para
wms_historico/wms_estado_hist. - Blob de área acima de alguns MB: reduzir o
tetoRemotodaquela área ou migrá-la para tabela relacional.
Imagens de produto
produto_imagens guarda o data URI (~120 KB) em coluna text. OK para centenas de produtos; para milhares, migrar para bucket do Storage e guardar só a URL.
Multi-coletor
Sem limite rígido. Pull ao abrir a aba, push debounced após salvar, pull de bloqueios_lote a cada 60 s, retry de pendências a cada 30 s. Gargalo é o Postgres/PostgREST do VPS — regra grosseira: 1 vCPU para cada ~15–20 coletores ativos bipando.
16 · Backup e recuperação de desastre
pg_dump diário do banco do WMS para armazenamento fora do VPS, com teste de restauração trimestral.# cron diário no VPS
0 2 * * * pg_dump -Fc -d "$WMS_DB_URL" | \
aws s3 cp - s3://backups-master/wms/wms-$(date +\%F).dump
| Dado | Onde persiste |
|---|---|
| Estado operacional (pedidos, estoque, movimentos, auditoria, áreas de sync) | Postgres do VPS + réplica parcial em cada coletor |
| Histórico além da janela / snapshot diário de configs | wms_historico / wms_estado_hist (append-only) |
| Histórico de conferências finalizadas, inventário rotativo, endereçamentos forçados | só no coletor (não sincroniza hoje) — export JSON do aparelho |
Recuperação: novo VPS + stack Supabase (mesmos domínios) → pg_restore do dump → reconfigurar secrets da Edge Function e a validação de JWT → republicar os arquivos estáticos → rodar supabase_policies_seguras.sql. Cada coletor, ao reconectar, faz merge do que não subiu (áreas eventos são união, sem perda).
17 · Monitoramento
| Sinal | Ação |
|---|---|
| Selo "N pendentes" / "sem conexão" (topo do app) | checar rede do coletor / disponibilidade do VPS |
| Faixa "armazenamento local cheio" (rodapé) | coletor saturado — sincronizar e recarregar; trocar por aparelho com mais espaço |
| Faixa vermelha "banco responde sem login" | crítico — políticas RLS não aplicadas; rodar supabase_policies_seguras.sql |
| Alerta "RPA parado" (aba Integrações + painel) | checar o fluxo do Power Automate |
| Tamanho do banco / conexões / logs (painel Supabase / VPS) | alertar em disco > 80%, picos de conexão |
18 · Checklist de implantação
| Bloco | Itens |
|---|---|
| Infra | VPS + Supabase no ar com TLS · hospedagem estática HTTPS · pg_dump diário + 1 teste de restauração |
| Entra ID | App single-tenant, SPA, Redirect URI exato · escopo access_as_user + admin consent · client/tenant ID anotados |
| Supabase | validação de JWT configurada · tabelas base · migracao_v8/v9 · supabase_policies_seguras.sql (conferir pg_policies = wms_entra_ok(), não true) · índices · PGRST_DB_MAX_ROWS · job de retenção |
| Front-end | WMS_CONFIG preenchido · CSP com hosts corretos · 4 arquivos + sw.js na mesma origem, CACHE incrementado · smoke test |
| Integrações | Edge Function com secrets + --no-verify-jwt · fluxo do Power Automate com service_role, rotação agendada |
| Operacional | perfis + vínculos, 1º Administrador, policies de bootstrap removidas · parâmetros da seção 11 · locais com tipo de área · produtos com embalagem + temperatura + tempo de vida · driver Zebra + etiqueta de teste · inventário inicial lançado |
Como usar
- Início: painel com os números da operação (atualiza a cada 60 s ou no botão Atualizar) e atalhos em ícones. Cada indicador é clicável e leva direto à tela correspondente. O menu lateral (☰, canto superior esquerdo) abre em qualquer tela e mostra pendências nos módulos.
- NF de Saída: a fila de trabalho. Uma NF nasce A separar, vai para A conferir quando o separador termina e fecha em Concluído automaticamente quando você finaliza a conferência dela. Entradas possíveis: cadastro manual, importação CSV do ERP (uma linha por item) ou Supabase, que compartilha a fila entre todos os aparelhos. O botão conferir carrega os itens da NF na lista esperada e já abre a aba de conferência.
A fila mostra por padrão só o que está em aberto (a separar / a conferir). Quando a NF é concluída ela sai da fila automaticamente — continua acessível no filtro Concluídos ou Todos os status.
Para o Supabase: preencha URL do projeto + chave anon + nome da tabela, use Testar conexão e Baixar SQL da tabela para criar a estrutura no banco. Sem configurar nada, o app funciona 100% local. - Gerar código (unidade): informe código, descrição, lote e validade → Gerar Código. Use Adicionar à fila para montar uma folha de etiquetas e imprimir todas de uma vez.
- Gerar código de caixa fechada: no card Caixa fechada / master, dê um identificador ao volume (ex.: CX-0001) e adicione uma linha por lote com a quantidade de unidades — 10, 12, 20, quantas houver. Uma caixa pode conter vários lotes e até vários códigos. O total é somado automaticamente e um único código representa o volume inteiro. A etiqueta impressa já sai com a lista de lotes ao lado do código.
Ao bipar esse código na conferência, o app dá baixa em todas as unidades de todos os lotes de uma vez e mostra uma linha de status por lote. Limite prático: ~15 lotes por código. - Recebimento: as notas entram por Nova NF, CSV (
nf;fornecedor;emissao;codigo;descricao;lote;validade;quantidade, uma linha por item) ou Supabase (tabelanotas_fiscais, com SQL para baixar). Abrindo a nota você tem os itens com lote, validade e situação de vencimento, e três caminhos:- Gerar e imprimir todas as etiquetas — código no padrão do app para todos os itens da nota.
- Imprimir etiquetas selecionadas — marque só os itens que precisa reetiquetar.
- Conferir esta nota — leva os itens da NF para a lista esperada e abre a conferência, validando código, lote, validade e quantidade contra a nota. Ao finalizar, a NF é marcada como Conferida com o resultado, o saldo recebe a entrada e o status sobe para o Supabase. A nota sai do Pré-Recebimento e da lista "A conferir" na hora — fica no filtro Conferidas (ou Todas) para consulta, e segue para a Armazenagem.
- Armazenagem: o passo seguinte ao recebimento. A fila A armazenar é alimentada pelas conferências de recebimento finalizadas, mostrando o que está na doca, de qual NF e quanto falta guardar. O processo tem três passos: 1) bipe o código do produto — o app já sugere a quantidade pendente e mostra onde esse lote está hoje; 2) ajuste a quantidade; 3) bipe o código do endereço e clique em Concluir armazenamento. A mesma câmera lê os dois códigos, identificando sozinha se é produto ou endereço.
Armazenar é uma transferência de endereço: sai da doca (ou do endereço com mais saldo) e entra na posição bipada — o saldo total não muda, e o movimento aparece no extrato como ARMAZENAGEM com o percurso origem → destino. Se o lote não tiver saldo em nenhum endereço, o app pergunta antes de lançar como entrada direta. O endereço bipado permanece selecionado depois de concluir, para você guardar vários itens na mesma posição em sequência. Bipar o código de uma caixa fechada preenche produto e quantidade de uma vez. - Transferência (grupo Inventário): remanejamento de endereço — mover um produto de um endereço para outro dentro do armazém. Não é entrada nem saída: o saldo total não muda e nada vai para o ERP. Quatro passos, todos por bipagem ou digitação: 1) origem · 2) produto/lote · 3) quantidade (já vem com o disponível da origem; botão Tudo) · 4) destino. Ao bipar a origem, o app lista o que existe ali com um botão usar por linha. Depois de concluir, origem e destino continuam para você mover vários itens seguidos; Inverter troca os dois. O botão Mover tudo deste endereço transfere todos os itens da posição de uma vez, validando um a um.
Validações antes de gravar: origem ≠ destino; nunca deixa saldo negativo; endereço de destino novo é cadastrado na hora; temperatura incompatível bloqueia (só Administrador força, com justificativa que vai para a auditoria); saldo reservado por NF de saída só é movido por quem tem a permissão de Inventário — e a reserva é remanejada junto para o novo endereço — e trava sem exceção se a NF já estiver em separação; lote em quarentena pode ser movido para a área bloqueada, com confirmação. O movimento aparece no extrato como TRANSFERÊNCIA, e a aba tem histórico próprio com filtros, KPIs e CSV. - Separação: a fila mostra as NF de Saída A separar. Ao abrir um, o app monta o roteiro: uma linha por item, ordenada pelo percurso do armazém (rua → módulo → nível), com o endereço vindo do inventário e o lote escolhido por FEFO — vence antes, sai antes. Endereços alternativos aparecem como "tb:" abaixo do principal.
Bipe o código do endereço e o app lista o que retirar ali; bipe o produto e a linha avança. Se o produto for bipado num endereço diferente do que o inventário aponta, ele conta mas avisa LOCAL DIFERENTE — sinal de endereçamento desatualizado. Sem saldo na posição, use ruptura: a conferência passa a esperar só o que realmente saiu. Concluir a separação é o que libera a NF para a conferência — antes disso ela não aparece lá. - Guia do próximo item: quando a quantidade lida bate com a solicitada, o app fecha a câmera e mostra um painel com o item concluído e o próximo a ler — código, lote, validade, quantas unidades faltam e o endereço. Clique em Continuar lendo para reabrir a câmera já apontada para o próximo, ou Dispensar para seguir manualmente. Ao fechar a última linha, o painel avisa que a conferência (ou a separação) está completa. Vale para a conferência e para a separação, e pode ser desligado na chave Pausar a câmera ao concluir cada item.
- Conferência: preencha operação e documento, monte a lista esperada (manual, importando CSV ou puxando uma NF já separada) e comece a bipar.
- Ocorrências de conferência (qualidade da separação): na conferência de Expedição, toda divergência entre o que foi separado e o que o conferente encontrou precisa de uma ocorrência registrada antes de concluir — o botão Finalizar fica bloqueado enquanto houver divergência sem ocorrência. Tipos: produto trocado, quantidade a maior/menor, lote diferente do alocado, validade fora do critério, avaria, item faltante. Cada ocorrência guarda NF, produto, lote, quantidade esperada e encontrada, tipo, o separador original, o conferente e a data/hora, mais uma observação livre. A ocorrência não apaga o registro da separação: o histórico continua mostrando o que foi separado errado, e a correção segue como um movimento normal de conferência.
A aba Indicadores tem o painel Taxa de erro de separação = linhas com ocorrência ÷ total de linhas separadas no período, com ranking por separador, quebra por tipo e por produto, evolução mensal e export CSV para o time de qualidade cruzar com os chamados do ERP. - Fechamento de carga (bipagem de volumes): cada volume fechado na Embalagem ganha um identificador único (etiqueta própria, código Data Matrix) vinculado à NF e ao romaneio quando a NF é despachada na Expedição. Na aba Fechamento de carga, ao entregar para a transportadora, o operador bipa volume a volume contra o romaneio: o romaneio só fecha com todos os volumes bipados. Volume faltante impede o fechamento; volume repetido ou de outro romaneio é recusado com aviso. Fica registrado quem fechou, a transportadora e o horário. Cargas em risco de perder o corte (Correios até 15h, demais até 16h — ajustável) aparecem destacadas na fila e num aviso na tela, mas não bloqueiam o fechamento.
- Produtos: a base única do almoxarifado — status, EAN, DUN (caixa/master), código, código interno, descrição, unidade, marca, fornecedor, dimensões, peso bruto, peso líquido, cubagem, periculosidade (texto livre + químico/tamanho/embalagem/temperatura) e tempo de vida. Entra por cadastro manual, CSV (
status;ean;codigo;codigo_interno;descricao;unidade;marca;fornecedor;dimensoes;peso_bruto;peso_liquido;cubagem;periculosidade;p_quimico;p_tamanho;p_embalagem;p_temperatura;tempo_vida;armazenamento;codigo_dun) ou Supabase (tabelaprodutos, com SQL para baixar e envio por upsert no código).
Tempo de vida é a validade total do produto em dias (ex.: 730) — com ela cadastrada, o app calcula sozinho o % de vida útil restante de cada lote nas NF de Saída, para o alerta de aprovação de envio.
O ganho maior está na leitura: com o EAN cadastrado, o operador pode bipar o código de barras do fabricante na conferência, na separação e na armazenagem — o app converte para o código oficial sozinho e ainda completa a descrição. O código interno também resolve. Produtos inativos saem do autocomplete. Pesos e cubagem aceitam vírgula decimal, e digitar as dimensões (30x20x15 cm) oferece a cubagem calculada. - Locais (Rua | Módulo | Nível): cadastre os endereços um a um ou gere faixas inteiras de uma vez (ex.: ruas 1–4, módulos 1–10, níveis 1–4 = 160 endereços). O código sai no padrão
RUA-00-00(ex.:A-01-01) e cada local tem etiqueta própria com o endereço em letra grande + código.
Na conferência, bipe primeiro o código do local: aparece a faixa “📍 Registrando em A-01-01” e todas as leituras seguintes ficam gravadas nesse endereço, até você bipar outro local ou clicar em limpar. A coluna Local do log e o bloco ENDEREÇAMENTO do CSV mostram o que foi guardado onde; a lista de locais mostra a ocupação registrada de cada posição. - Resultado por leitura:
- OK código e lote conferem com a lista.
- LOTE DIVERGENTE o código existe na lista, mas o lote é outro.
- NÃO PREVISTO item que não consta na lista.
- EXCEDENTE quantidade lida acima do esperado.
- DUPLICADO / VALIDADE mesma etiqueta bipada de novo, ou validade vencida/próxima (90 dias).
- FALTANTE item esperado que não foi bipado até o fim.
- Inventário: lance código, lote, validade, quantidade e localização (obrigatória) — sem endereço o produto não entra no roteiro de separação. Endereço novo no padrão
RUA-00-00(ex.:A-01-01) é cadastrado em Locais na hora, com sua confirmação. O campo Local continua preenchido depois de lançar, para você cadastrar vários lotes da mesma posição em sequência. Na importação, a 6ª coluna do CSV é o local e linhas sem endereço são recusadas e listadas; no Supabase (botão na própria aba, usando a conexão da aba NF de Saída) o envio é upsert porcodigo,lote,local. A tabela mostra a posição de estoque com KPIs de unidades, vencidos e a vencer em 90 dias, e filtros rápidos. O botão Gerar e imprimir etiquetas monta a folha de códigos dos itens marcados (ou dos filtrados, se nada estiver marcado) e abre a impressão direto — com a opção de 1 etiqueta por unidade para reetiquetar caixa por caixa. Enviar seleção p/ conferência transforma o inventário na lista esperada para você contar bipando as prateleiras. - Saldo: consulta por código + lote com entradas, saídas, endereços, situação de validade e último movimento. O saldo parte do que foi lançado no inventário e é movimentado pelas conferências finalizadas — recebimento soma, expedição subtrai, conferência de inventário não movimenta. Só leituras validadas movimentam: divergências (lote errado, não previsto, vencido, excedente) ficam fora. O botão extrato de cada linha filtra o kardex daquele item.
Na expedição, se o endereço bipado não tem a linha do lote, a baixa sai do endereço cadastrado por FEFO. Vender item sem cadastro deixa saldo negativo — é proposital, aparece em vermelho no painel e na aba para você corrigir o inventário em vez de esconder o erro. No recebimento sem endereço bipado, o app pergunta a posição de destino antes de dar entrada. - Encerrar: Finalizar e salvar grava no histórico. Exporte o CSV para anexar ao processo.
Impressão — Zebra TLP 2844 · etiqueta 50 × 30 mm
Todas as etiquetas do app já saem no tamanho exato 50 × 30 mm, uma por etiqueta do rolo (uma carreira na horizontal). A página de impressão é configurada automaticamente para 50×30 mm sem margens quando você clica em qualquer botão de imprimir etiquetas.
Tamanhos disponíveis (o de local é escolhido na aba Locais):
- 50 × 30 mm — produto, caixa fechada e local de prateleira. Stock 50,8 × 30 mm, uma carreira.
- 50 × 30 mm em rolo de 2 carreiras — duas etiquetas de produto por avanço. Escolha o rolo no seletor da fila de etiquetas (aba Gerar Código) ou no inventário.
- Deitadas: as duas lado a lado, página de 100 × 30 mm — no driver, stock 101,6 × 30 mm.
- Na vertical: cada etiqueta gira 90° e ocupa 30 × 50 mm, página de 60 × 50 mm — no driver, stock 60 × 50,8 mm, orientação retrato.
- Se o número de etiquetas for ímpar, a última página sai com a segunda posição em branco.
- 100 × 50 mm deitada — local de porta-palete. Endereço em 13 mm de altura, código de 23 mm. Stock 101,6 × 50,8 mm.
- 100 × 35 mm deitada — local de porta-palete em rolo mais estreito. Endereço em 10 mm, código de 15 mm. Stock 101,6 × 35 mm.
- Versões "na vertical" — a mesma etiqueta girada 90°, para colar na coluna do porta-palete. A página troca de lado: 100 × 50 vira 50,8 × 101,6 mm e 100 × 35 vira 35 × 101,6 mm no driver. Mantenha a orientação retrato — a rotação já vem no desenho, não marque "paisagem".
- 100 × 150 mm e 100 × 100 mm — 1 carreira — etiqueta grande (mesmo conteúdo das 50 × 30, ampliado) para produto, embalagem, local e caixa de separação. Escolha em cada tela: rolo de produto (aba Gerar Código / inventário), aba Locais (local e caixa de separação) e card "Etiqueta da embalagem". Página 100 × 150 mm / 100 × 100 mm sem margem, uma etiqueta por avanço.
Desde a v56, os layouts são editáveis pelo Administrador na aba Etiquetas (grupo Cadastros) — tamanho, elementos, campos e novos modelos. Os tamanhos acima são os modelos-padrão; "Restaurar padrão" volta qualquer um ao original.
Como o tamanho de página é único por impressão, quando a fila tiver etiquetas de tamanhos diferentes o app mostra um botão para cada tamanho — imprima uma rodada por rolo.
No driver da impressora (uma vez só):
- Painel de Controle → Dispositivos e Impressoras → botão direito na ZDesigner TLP 2844 → Preferências de impressão.
- Tamanho do papel / Stock: personalizado 50,8 mm × 30 mm (2,00" × 1,18"). Margens: 0 em todos os lados.
- Media type: térmica direta (etiqueta térmica) — ou transferência térmica se usar ribbon. Tracking: Web sensing (gap entre etiquetas).
- Velocidade 2–3 ips e escurecimento (darkness) 8–12: código muito claro não lê, muito escuro borra os módulos.
- Rode a calibração do rolo antes do primeiro lote (botão de feed pressionado até piscar, ou pelo utilitário Zebra).
Na janela de impressão do navegador: destino = ZDesigner TLP 2844 · escala 100% (nunca "ajustar à página") · margens nenhuma · desmarque cabeçalhos e rodapés e gráficos de fundo não é necessário marcar.
Densidade do código: o Data Matrix (padrão ECC200) ajusta automaticamente o tamanho da matriz ao conteúdo, sem "nível de correção" configurável como no QR, e com bem mais capacidade que um QR do mesmo tamanho físico. Etiquetas de caixa com muitos lotes ainda geram um código mais denso — o app avisa acima de ~320 caracteres (cerca de 6 lotes), com boa folga antes de comprometer a leitura.
v8 — embalagem, temperatura, imagem e Data Matrix
- Embalagem: em Produtos, cadastre a menor unidade, o fator da caixa (1 CX = N UN) e do pallet (1 PL = N CX). Fatores só aceitam inteiro ≥ 1. O saldo é sempre guardado na menor unidade — em Recebimento (Nova NF), Inventário (lançar) e Separação (passo dos botões +/−) você escolhe em qual unidade digita e o app converte. Produtos sem embalagem entram na lista de pendências de cadastro (aba Produtos) e são tratados como unidade.
- Temperatura: no produto informe a faixa (°C) — o tipo Ambiente / Refrigerado 2–8 / Congelado é derivado (o seletor Condição de armazenamento ainda sobrepõe manualmente). Em Locais, cada endereço tem um Tipo de área. No endereçamento (recebimento, armazenagem, devolução, inventário) o app bloqueia posição incompatível e mostra o tipo exigido × o do endereço. Só o perfil Administrador força, sempre com justificativa registrada na Auditoria. O relatório Itens em endereço incompatível (aba Inventário) lista o que já estava divergente.
- Imagem: upload no produto — redimensionada para ~480 px e guardada na VPS (tabela
produto_imagens); cada aparelho mantém cache local (IndexedDB). Miniatura aparece nas listas de Separação, Conferência, Conferência de Recebimento e Inventário ao lado da descrição; um toque amplia. Ao bipar um produto, a foto também aparece no cartão de resultado da leitura em todos os processos (Conferência, Recebimento, Separação, Armazenagem, Inventário, Devolução) — para conferência visual na hora. Produto sem foto: o cartão aparece sem imagem, sem ocupar espaço. - Ritmo de bipagem: o app exige 1 segundo entre a leitura de um produto e a do próximo — dá tempo de olhar a foto e a descrição antes de seguir, e evita contagem dobrada por eco do leitor ou disparo repetido da câmera. Leitura chegada cedo demais mostra "Aguarde 1 segundo" e é ignorada (basta bipar de novo). Bipar o endereço ou uma caixa fechada não entra nessa trava.
- Data Matrix GS1: a bipagem já lê o Data Matrix do fabricante com os AIs
(01)GTIN,(10)lote,(17)validade,(21)série e o separador FNC1 (além do formato calibrado por produto). Para item sem código de fábrica, a etiqueta interna do app já é um Data Matrix com produto + lote + validade; marque etiqueta interna GS1 na aba de etiquetas da NF para gerar no padrão GS1(01)(17)(10)(ou(91)com o código interno quando não há EAN) — reconhecida depois como equivalente à do fabricante. A mesma rotina de etiqueta é usada na contagem de inventário.
Código de barras linear (Code 128, Code 39 etc.) de teste rápido / IVD com código, lote e validade separados por espaço, TAB ou vírgula — em qualquer ordem (ex.:30100166 0001191522 05/11/2027): o token que for uma data (dd/mm/aaaa,dd-mm-aa,aaaammdd) vira a validade, os outros viram código e lote. É lido direto, sem formato calibrado. Se um item desse tipo estiver lendo o lote errado, abra o produto e apague os campos da seção "Formato da etiqueta do fabricante". Campos colados sem separador continuam exigindo o formato calibrado no produto. - Que códigos de barras o app lê: no leitor USB o próprio aparelho decodifica e "digita" o texto — o app aceita qualquer texto; se um leitor novo não lê um tipo (EAN, ITF-14/DUN, Code 128, QR…), habilite a simbologia no manual do leitor (folha de códigos de configuração). Na câmera (celular/tablet) o app pede ao navegador todas as simbologias que ele souber decodificar — EAN-13/8, UPC-A/E, ITF-14/DUN, Code 128/39/93, Codabar, QR, Data Matrix, PDF417, Aztec. Funciona melhor no Chrome/Android; em navegadores sem leitor nativo (Firefox, Safari de computador) a câmera lê só QR — nesses use o leitor USB.
- Curva ABC e posição no armazém: a curva cadastrada no produto (A/B/C) passou a decidir onde ele é guardado, não só a frequência de contagem no inventário rotativo. Curva A vai para posição perto do início do percurso e em nível baixo; curva C vai para o fundo e para o alto, liberando as posições boas para quem gira. Consolidar o produto onde ele já tem saldo continua tendo prioridade — a curva é o critério de desempate. O card Reslotting (aba Indicadores) lista quem está fora da posição da curva, com o endereço sugerido e um CSV para o remanejamento.
- Formato da etiqueta do fabricante (por produto): no cadastro do produto, a seção Formato da etiqueta do fabricante calibra a leitura quando a etiqueta vem num layout de largura fixa (campos colados, sem separador). O campo Reconhecer pelo código de barras aceita uma etiqueta real (leitor USB ou colada): o app identifica onde ficam código, lote e validade (usa o código/EAN do próprio produto como âncora) e preenche o formato para você revisar e testar. Copiar de outro produto: bipe/digite o código de um produto já cadastrado e o app traz o formato dele — útil para famílias que repetem o layout de etiqueta. Deixe sem campos para usar o leitor genérico. Códigos GS1 ou com campos separados por espaço/vírgula não precisam de formato — o app avisa.
Entrada de mercadoria — compra x devolução
- Recebimento de compra: conferência normal contra o pedido/NF (código, quantidade, lote, validade). Item que chega com validade abaixo do padrão da saída (mesmo % de vida útil da expedição, configurável em Configurações → Entrada de mercadoria) fica PENDENTE DE LIBERAÇÃO e não entra em estoque disponível. Não há recusa automática. Na finalização o app oferece o e-mail ao comprador. Na aba Recebimento → Liberação de validade, só o perfil de Compras libera (com endereço sugerido — temperatura compatível e lote lado a lado) ou recusa, sempre com justificativa. Fica registrado quem recebeu, quem liberou e a data/hora de cada etapa.
- Devolução de cliente: fluxo próprio (aba Devolução), aberto por número de nota de devolução ou pelo chamado do ERP. Todo item entra BLOQUEADO em quarentena — saldo visível, mas indisponível para separação (nenhum perfil de operação separa lote bloqueado). Na aba Devolução → Decisão de qualidade, só o perfil de Qualidade decide item a item: liberar (volta ao disponível, com escolha do endereço), manter em quarentena ou descartar — sempre com motivo tipificado (produto errado enviado, item faltante, pedido de venda incorreto, avaria, temperatura, validade, outro) + campo livre. Histórico completo por item devolvido. Sem prazo limite de devolução.
- Produto vencido / área bloqueada: ao virar a validade, o lote é bloqueado automaticamente (uma vez por dia, na abertura do app) e, se um endereço da área bloqueada estiver configurado, o saldo é movido para lá. Item bloqueado nunca aparece na sugestão de separação. Em Devolução → Área bloqueada e descarte: marque os lotes, gere a lista de recolhimento (CSV para a terceirizada) e registre a baixa com o responsável — o saldo é zerado e o movimento fica no extrato.
Formato do código
Unidade: MD|codigo|lote|validade|descricao
Caixa fechada: MDX|id|embalagem|total|cod*lote*validade*qtd*desc~cod*lote*validade*qtd*desc (lotes separados por ~).
Local: MDL|A-01-01|A|01|01|setor (a etiqueta de local no app leva só o código A-01-01)
Etiqueta interna GS1: Data Matrix (01)(17)(10) quando há EAN; senão (91)codigo(17)(10) (etiquetas antigas em (240) continuam sendo lidas).
Na leitura ele também entende:
JSON ({"codigo":"...","lote":"..."}), pares chave=valor separados por | ou ;,
GS1 (Data Matrix ou parênteses) com AIs (01)(10)(17)(21)(91)(240)(241) e FNC1, e, como último recurso, CODIGO|LOTE ou só o código.
Celular, tablet e computador
O app se adapta ao tamanho da tela: no celular as tabelas viram cartões (um item por bloco, sem rolagem lateral), os botões ganham área de toque de 44 px para uso com luva, os campos usam fonte 16 px para o iPhone não dar zoom ao focar e o resultado da leitura fica fixo no rodapé enquanto você bipa. No tablet os formulários se reorganizam em 2–3 colunas e no computador em 4. Vale adicionar à tela inicial (Chrome: menu → Adicionar à tela inicial; Safari: Compartilhar → Adicionar à Tela de Início) para abrir em tela cheia como um aplicativo.
Requisitos da câmera
Para a câmera funcionar, a página precisa ser aberta em https:// ou em localhost (exigência dos navegadores). Em celular Android/Chrome a leitura usa o detector nativo, sem depender de internet. No iPhone use o Safari.
Publicar online
É um arquivo único: suba em qualquer hospedagem estática (GitHub Pages, Netlify, IIS/Apache interno) e acesse pelo celular. Também funciona salvo na rede e aberto direto do arquivo, mas nesse caso a câmera pode ser bloqueada — use a entrada manual/leitor pistola.