🚀
Versão atual
v2.37.1085
JP Embalagem · Sistema de Controle de Produção
📜 Histórico de versões
v2.37.1085
🏢 O MESMO SISTEMA PRA OUTRA EMPRESA: A DM7. Dono 25/10/2026: "quero que seja igual o sistema da JP … o nome tem que entrar como o domínio … tem que vir com isso tudo vazio … a logo que for colocada na empresa tem que aparecer em todos os formulários, orçamento e tudo mais". A DM7 (dm7.embalagem.app.br) passa a rodar este sistema, com banco próprio e vazio, ligada no Painel MTX: entra com senha de verdade (a sessão fica no servidor), cada pessoa vê só os módulos que a empresa contratou, tablet e celular entram uma vez com o código de 6 números, empresa bloqueada vê "Acesso suspenso, fale com a MTX", e usuário se cadastra pela Equipe.
🏷️ Nome e logo de cada empresa em tudo. Lá aparece o nome e a logo da DM7 (sem logo cadastrada, as letras "DM7"), nunca "JP EMBALAGEM" nem Boracéia — tela de entrar, topo, apps, orçamento, romaneio, e-mails.
🔒 Não muda nada na JP: tudo isso só liga numa empresa criada pelo Painel MTX. Aqui o login, os aparelhos, o nome, a logo e as telas continuam exatamente como estavam.
🔧 Por dentro: api/src/plataforma/ (a camada que veio do MTX v2.37.247) só monta com PLAT_DB_* no .env; o login dela também emite o crachá daqui (X-JP-Sessao), então o RBAC e o admin original valem igual; módulo desligado lê vazio e grava 403; js/135 (sessão/tablet/bloqueio/faixa do suporte), js/136 (os 14 módulos no menu e nos apps), js/47-marca (nome/logo/iniciais/troca do texto fixo, só com sessao:true), lib/nome-casa.js (e-mails). Preview aprovado Kc2vPppK9FHEHCVjG3Wh3V ("pode fazer. 1 sim, 2 letras DM7, 3 pode, 4 só a compra de chapa na JP"). Testes: 24 da plataforma (duas empresas de verdade em Postgres de teste) + a suíte inteira da JP comparada com a main: nenhuma falha nova.
v2.37.1084
🛒 COMPRA DE CHAPA — O MÓDULO QUE LIGA E DESLIGA (PRA EMPRESA QUE COMPRA A CHAPA, COMO A DM7). Dono em 25/10/2026: "a JP faz a chapa e compra bobina; outros clientes compram a chapa — quando entrar o pedido, a programação tem que gerar uma ordem de compra com a chapa e os vincos cadastrados … enviar por e-mail ou WhatsApp … quando chegar, entrada manual ou nota fiscal, e a nota tem que vir exatamente com o pedido de compra … e a condição de pagamento, que mora no cadastro do fornecedor".
🧩 A chave: Cadastros → Empresa → 🧩 Módulos → 🛒 Compra de Chapa (vale pra todo mundo depois de 💾 Salvar). Desligado = o sistema de hoje, sem uma vírgula de diferença — a JP segue com a onduladeira e as bobinas.
✅ Ligado: no PCP, o Programar vira "Programar e pedir a chapa": a ordem de compra nasce sozinha com a chapa, a medida, os vincos (riscador) e a quantidade do cadastro da caixa — caixa de dobra pede +3% de sobra; corte e vinco sai chapa lisa, sem vinco, quantidade = caixas ÷ poses +5%; chegar até a entrega − 2 dias; pedidos da mesma chapa entram na mesma OC (uma linha por pedido). Cadastro sem chapa, medida ou vinco: a OC não nasce e a tela diz o que falta. A fila mostra "aguardando chapa · OC-0001" em vez do "Chapa produziu".
📤 Aba nova Produção → 🛒 Compra de Chapa: escolhe o fornecedor (categoria 📦 Chapa do cadastro), vê a 💳 condição de pagamento e a forma (Boleto/PIX/TED) do cadastro do fornecedor — ou troca só nesta OC —, abre o papel/PDF (cabeçalho da empresa, itens, desenho das chapas, quadro da NF, condição de pagamento) e manda por e-mail (o servidor manda, com o link do papel) ou WhatsApp (texto pronto). Sem condição de pagamento a OC não vai. A condição e a forma são copiadas pra OC na hora de mandar: o papel que o fornecedor recebeu não muda se o cadastro mudar depois.
📦 Quando a chapa chega: 📦 Receber pela NF-e (XML) — confere o nº da OC (xPed), o item (nItemPed), o CNPJ, a medida, o vinco e a quantidade (até ±5%); bateu, entra sozinha; não bateu, fica em conferir com o motivo escrito (ou entra "mesmo assim", com o motivo gravado) — ou manual (escolhe a linha da OC e conta). A chapa entra em Estoque → Chapas reservada pro pedido (com NF, OC e pedido na linha) e o pedido vai sozinho pra material disponível, com as chapas que chegaram no mesmo campo do "Chapa produziu".
🔒 Não muda: a JP com o módulo desligado (onduladeira, bobinas, Programar, fila); as compras de insumo e o 🛒 Pedidos de Compra do Financeiro; a leitura da NF-e (só ganhou xPed/nItemPed); a ficha do fornecedor (a OC só lê a seção Pagar); cadastro de caixa, preço, orçamento, app do operador. Fora desta versão: baixa do estoque quando o pedido termina e contas a pagar a partir da NF.
🔧 Por dentro: js/133-compra-chapa.js (JPCompraChapa, puro: linhaDoPedido / encaixar / podeMandar / aoMandar / conferirNF / aplicarRecebimento / papelHTML / textoWhatsApp — roda na tela, no teste e no servidor por vm) + js/134-compra-chapa-tela.js (a chave em #emp-modulos, os ganchos jpCompraChapaModalProgramar/jpCompraChapaFila no js/15, a aba #ccp-root, receber). Dado: snapshot compra_chapa = {ocs:{id:oc}} por /merge; no pedido programacao.compraChapa. API: routes/compra-chapa.js — POST /api/compra-chapa/:id/email (com login) e GET /api/compra-chapa-papel/:id?t=token (aberta, por token). js/08 salvarDadosEmpresa leva modulos; js/01/07 aba compra-chapa; js/03 reserva pelo pedidoId; js/65 xPed/nItemPed. Preview aprovado 3tQJsbgmKkRDmKXDMapeLq (v4). Teste: tests/compra-chapa (142, 5 mutações pegas). ⚠️ Precisa pm2 restart da API.
v2.37.1083
📦 O PALETE DA CAIXA COLADA COM O SLOTTER E AS FITAS, NO OPERADOR E NO CADASTRO. Dono em 25/10/2026, depois do recorte da caixa aberta (v2.37.1080): "pode fazer isso com todas as caixas … na verdade só iria aparecer o slotter da caixa; o desenho já é feito e nós já exportamos em DXF — a caixa dobrada fica do mesmo jeito na conta, porém com o slotter aparecendo" e "deixa com a fita amarrada também".
✅ O que muda: toda caixa colada (maleta/slotter) mostra o pacote dobrado com os dois painéis, o vinco entre eles (tracejado azul), os cortes do slotter nas abas (as fendas como entalhes na borda) e as duas fitas do amarrado, nos 3 desenhos — na 📦 Ficha de paletização do app do operador e na seção 8 · Paletização do cadastro. A faca é a mesma que o sistema já gera pelas medidas (a do botão de DXF/EPS), ou o DXF guardado na caixa, dobrada ao meio no lado que o palete já decide; a aba de cola fica embaixo. Hoje são 237 caixas coladas (6 com DXF). A fita volta também no pacote recortado da caixa aberta (TAMPA REVAL, CX M), que saía sem desde a v2.37.1080. Legenda da vista de cima: "slotter da faca (dobrada)".
🔒 Não muda: lastro, camadas, caixas por palete, paletes a usar e o tamanho do pacote (NACON 16 KIT FILME: 5 × 15 = 1.875; KININO CX 23: 2 × 7 = 350); caixa colada sem medida interna fica o bloco liso; cadastro, DXF/EPS, PCP, etiqueta, banco.
🔧 Por dentro: js/19-paletizacao.js palFacaGeoDaCaixa(cx) (DXF de cx.cv.dxf pelo cvContornoDoDxf, senão jpFacaDaMaleta do js/106 → riscos com Y pra baixo), palOrientarFaca (o vulto no chapaC; chapa ao contrário transpõe), palGeoDobrada(geo, lado, aba) (metade depois da aba de cola até o vinco do meio, até 15 mm; vinco da dobra vira corte; aba à direita espelha; dobra em L transpõe) e params.facaGeo no palCalcular — só pra caixa colada, dxfGeo solto segue ignorado; fitasIso compartilhada pelo bloco e pelo recortado; as 3 condições de desenho sem o semDobra. js/23c cvGeoDeTracos (o fechador do anel, um só). painel_operador.html carrega o js/106 e _opFacaGeoDaCaixa; js/08 palRenderCadastro monta a faca de cxCaixaDoForm() + cvDxfColetar(). Preview aprovado 8kSqu7YG5Xb85eNtofAUjJ v2. Teste: tests/palete-slotter-colada (45, 6 mutações pegas). Conferido no navegador com a NACON real (slotter + vincos + 160 fitas, 1.875) e a TAMPA REVAL (recorte + fita de volta, 1.800); o cadastro pelo palRenderCadastro real com os campos da NACON. Bateria do palete: nenhuma falha nova (faca-em-eps, plano-fiacao e palete-arte-dobrada já falhavam na main).
v2.37.1082
📦 PARA ONDE FOI A CAIXA — A SOMA VEM DA MÁQUINA DE CORTE. Dono em 25/10/2026, depois do aviso de palete sem ✓ (v2.37.1070): "se digitar 1000, é mil que tem que ir para a coladeira; se faltar pode ser perda, quero que aponte aonde perdeu — a coladeira passou 950, perdeu 10, esses 40 ele tem que dizer pra onde foi".
✅ O que muda (app do operador, toda etapa depois do corte — Coladeira, Grampeadeira…): ao ✅ Finalizar com menos que o corte entregou, abre "📦 Para onde foi a caixa?" com a conta (Slotter entregou · você fechou · diferença) e três destinos que se somam: 🔧 perdi aqui (com motivo) · ⬅️ já veio a menos da Slotter · 📦 ainda está na máquina (o pedido continua aberto pro próximo). Só finaliza quando a conta fecha; não existe mais "Não perdi nada" com diferença no ar. Diferença grande (acima dos 10%) passa pela mesma janela — antes caía no "Acabou o material?" e sumia sem dono. No PCP, o "veio a menos" aparece no histórico do pedido como "⬅️ Slotter entregou a menos N cx · conferir" (aviso, não é perda no nome de ninguém). Fechou mais que o corte: não trava nem pergunta, segue e monta os paletes; o último palete não tem limite (a régua do cadastro vale só pros de trás). Perda do ajuste já apontada desconta da diferença.
🔒 Não muda: bateu com o corte → a janela de perdas de sempre; Slotter / Corte e Vinco ("Acabou a chapa?"); fim do turno; aviso de palete sem ✓; Estoque PA, expedição e etiqueta.
🔧 Por dentro: painel_operador.html — _contaDoCorte (corte entregou − fechou − ajuste − já destinado em registro vivo), _destinosDaCaixa, _abrirParaOndeFoi no _finalizarComQtd (_depoisDoCorte: sem trava/acumulado pela régua do corte, sem "Acabou o material?"); registro do Finalizar e parcial de turno levam veioAMenos; _paletesNaoCabem ignora o último palete. js/01-core.js — _veioTxt no histórico. Preview aprovado HQkH9Lg3K6oKwPGJEqhMeS. Teste: tests/para-onde-foi-a-caixa.
v2.37.1081
🔁 TROCA DE TURNO: PASSOU DA CHAPA, NÃO TEM "FIZ SOZINHO". Dono, 25/10/2026: no 24332 TAMPA REVAL (15.000 chapas = 30.000 cx) o turno do Fabricio fechou sozinho às 14:50 gravando 19.004 cx, e o Arnaldo finalizou com 24.452 chapas no campo (o visor não zera). O aviso "🔁 Confere o número" abriu, mas o botão "Fiz sozinho mesmo" deixou a máquina com 48.904.
✅ O que muda: no Finalizar do app do operador, quando já tem produção anterior e o total passa do material que existe (chapa lançada, ou o que o corte entregou) + 10%, o aviso abre sem o "Fiz sozinho mesmo"; o verde diz quanto vai lançar e com quanto a máquina fica. O "Só deste apontamento" do "Já lançado hoje" também não passa por cima.
🔒 Não muda: dentro da chapa tudo igual; pedido sem chapa lançada segue com o "Fiz sozinho"; com palete confirmado segue igual; fim de turno e "⏭ passar pro próximo" iguais (a parte do turno que fecha sozinho fica com os sensores).
🔧 Por dentro: painel_operador.html _finalizarComQtd ganha _trava (meta física pela base do _saldoDaEtapa, sem palete, com feitoAntes, total > meta + tol) que vale mesmo com jaConferiuAcumulado; abrirAvisoAcumulado com info.trava tira o acum-tudo e mostra no verde o _quantoFaltaLancar do corrigido. Preview aprovado Ct46j4WZHZUwAQwdv2zjuB ("pode fazer só a mudança 2, a 1 os sensores resolvem"). Teste: tests/troca-de-turno-trava-acima-da-chapa (13, 2 mutações pegas).
v2.37.1080
📦 O PALETE DO APP DO OPERADOR COM O RECORTE DA FACA, IGUAL AO CADASTRO. Dono em 25/10/2026, com a TAMPA REVAL no tablet (blocos lisos) e a CX M no cadastro (silhueta da faca): "a forma que aparece os palete no app do operador seja igual aparece no cadastro da caixa com o corte de caixas, assim o operador sabe como fazer os paletes mais preciso".
✅ O que muda: na 📦 Ficha de paletização do app do operador, as caixas que vão abertas e têm o DXF da faca guardado mostram a forma real da faca (vinco tracejado azul) na vista de cima, na 1ª camada e no palete completo, e embaixo da vista de cima o mesmo aviso do cadastro ("camada ímpar", "padrão simétrico"). Um desenho embaixo do outro no tablet, como antes. Hoje são 11 caixas (REVAL, DCX, KININO 22, FK, TRANSBERNAL…).
🔒 Não muda: lastro, camadas, caixas por palete e paletes a usar; caixa colada (sem recorte); cadastro, PCP, etiqueta e banco.
🔧 Por dentro: o desenho (js/19) já era o mesmo; só o cadastro passava o dxfGeo. painel_operador.html carrega o js/23c-corte-vinco-dxf.js (o leitor de DXF do sistema, um só na casa) e _opDxfGeoDaCaixa tira o recorte de caixa.cv.dxf por cvContornoDoDxf, só com semDobra (a regra do js/08); renderFichaPaletizacao passa ele pro palCalcular e mostra o palCapTop. Preview aprovado CdStx2ikYB3jmNWBPmkWt5 ("pode fazer, um desenho embaixo do outro no tablet"). Teste: tests/palete-recorte-no-operador (17, mutação pega). Conferido no navegador com a TAMPA REVAL real: 4 na base (caracol) × 9 camadas = 1.800, recorte nos 3 desenhos.
v2.37.1079
🗂️ LANÇAMENTO ARQUIVADO SAI DA CONTA DO OPERADOR. Dono, 25/10/2026: a TAMPA REVAL (24332) saiu 29.900, mas o app do operador mostrava "Máq. A Corte e Vinco · CONCLUÍDO · 48.901cx" — a soma com o parcial de fim de turno do Fabricio (19.004), que tinha sido arquivado em 07/10. Arquivar tirava do histórico e do estoque, mas o número da máquina no operador só era refeito quando ela ficava sem nenhum lançamento.
✅ O que muda: arquivar um lançamento no 📜 Histórico da produção refaz na hora o número da máquina no app do operador, só com os lançamentos que sobraram (no corte, menos as perdas, como já era). O ✏️ qtd faz a mesma conta. Corrigidos no banco: 24332 TAMPA REVAL 48.901 → 29.897 e 24386 BLUE SEA CX 220007 (Coladeira) 4.361 → 3.132.
🔒 Não muda: histórico, lançamentos e estoque; a máquina continua CONCLUÍDA; pedido carregado ou entregue não é mexido.
🔧 Por dentro: js/01-core.js jpQtdEtapaPelosVivos + jpRecontarEtapaDoOperador (etapa concluída, com lançamento vivo e número diferente → grava em etapas[slot], no overlay_operador e no concluidos_operador); chamada no × Arquivar quando a v2.37.674 não soltou a etapa e no jpGravarQtdRegistro (que gravava só o número do lançamento corrigido, e com a chave corte_vinco, que não é o slot). Backup do banco em /root/backups-claude/2026-10-25-arquivado-conta-*. Preview aprovado 7VdzuPHSHwnRBbPdrKq2hQ ("pode fazer, 29.897, e corrige o BLUE SEA junto"). Teste: tests/arquivado-sai-da-conta-operador (17, mutações pegas).
v2.37.1078
🔒 DOIS PACOTES DA API COM FALHA CONHECIDA ATUALIZADOS. Revisão de segurança de 25/10/2026, item 3: body-parser 1.20.8 → 1.20.9 (um pedido compactado com lixo no fim podia derrubar o sistema) e proxy-addr 2.0.7 → 2.0.8 (falha de IP falso que não se aplicava à nossa configuração, mas fica corrigida). npm audit da API: 0 falhas.
🔒 Não muda: nada que se vê; só a última casa da versão dos dois pacotes.
🔧 Por dentro: só api/package-lock.json (npm audit fix --package-lock-only). Testado numa cópia isolada, sem banco: JSON normal, arte de 10 MB, limite de 15 MB (413), gzip normal e gzip com lixo no fim (recusado, 400). O servidor instala e reinicia sozinho (mtx-auto-deploy).
v2.37.1077
🔒 A TRAVA DO LOGIN CONTA PELO IP DE VERDADE. Revisão de segurança de 25/10/2026: o sistema lia o IP do primeiro nome de uma lista que o próprio visitante pode escrever (X-Forwarded-For). Inventando um IP novo a cada tentativa, dava pra driblar a trava de 15 tentativas de senha, e o IP gravado no aceite do orçamento e na auditoria podia ser falso.
✅ O que muda: as travas do login (sistema, vendedor, senha mestre, esqueci/trocar/definir senha), dos portais (cliente, aceite de orçamento, fornecedor, papel, recebimento) e o registro de acessos usam o IP que o próprio servidor viu — vale na Hostinger e no PC da fábrica.
🔒 Não muda: telas, senhas, logins; os limites de tentativa; os registros antigos.
🔧 Por dentro: api/src/lib/auditoria-puro.js ipDoPedido vira a única régua do IP — lê o X-Forwarded-For de trás pra frente pulando só o loopback (nginx com $proxy_add_x_forwarded_for e o servidor-telas.mjs do PC acrescentam o real no fim); conexão que não vem do próprio servidor = IP da conexão. Trocado em auth.js, orcamentos.js, portal.js, portal-orcamento.js, portal-recebimento.js, portal-fornecedor.js, portal-papel.js. No mesmo dia, no servidor: SSH só por chave + fail2ban. Preview aprovado 1nc4s741CaV6SJR6CsZFjY ("pode fazer o conserto da trava do login"). Teste: tests/ip-real-trava-login (26, mutação pega).
v2.37.1076
🏷️ "ABAIXO DO CADASTRO" SOME QUANDO O CADASTRO FOI AJUSTADO DEPOIS. Dono em 24/10/2026, com a PAPELARIA REVAL · CX M na tela: "está com o preço certo, mas está mostrando para o vendedor e pra mim que está abaixo do preço". O Armando lançou 5.500 cx a R$ 1,870 em 22/10 20:54 com o cadastro em R$ 1,918; o cadastro foi ajustado pra 1,870 às 22:06, e o pedido aceito seguia "R$ 264,00 a menos".
✅ O que muda: o aviso vermelho só fica se o preço estiver abaixo também do cadastro de hoje (com o reajuste do cliente). Ajustado depois → Comercial → Solicitações mostra "= mesmo preço do cadastro · no lançamento era 1,918; ajustado em 22/10 22:06", e o app do vendedor mostra "✓ preço do cadastro".
🔒 Não muda: preço e total do pedido; o que ficou gravado nele; pedido ainda abaixo do cadastro de hoje (segue vermelho); a trava do app ao lançar abaixo; comissão (só aviso, nada é descontado sozinho).
🔧 Por dentro: js/09-logistica.js pvPrecoRef (a régua do cartão, do relatório, da folha e do Lançar) devolve a referência de hoje com ajustadoDe/ajustadoEm (histórico de preço, js/92); painel_vendedor.html pvAbaixoHoje. Preview aprovado MeRkRTFnGdwtGjLfjZYuqn ("pode fazer", nota só pro PCP). Teste: tests/abaixo-cadastro-ajustado-depois (18, mutação pega).
v2.37.1075
📦 TELA DE BIPAR: "FALTA BIPAR" POR CLIENTE. Dono em 23/10/2026, com o "Conferir o que tem no estoque" pedindo ADORA de novo: "já foi selecionado o cliente no início, não tem necessidade de aparecer aqui novamente — quero que aparece ex: cliente ADORA 3 paletes e bipou 1 aparece falta 2 e quando concluir aparece concluído" + "barra de processo mais visível" + "quando concluir fica verde".
✅ O que muda (app da Expedição, carregamento aberto): saem os seletores de cliente e modelo; entra 📦 Falta bipar — um cartão por cliente da carga com N pal · bipou X · falta Y, barra grossa com "% · X de N paletes" (amarela enchendo), e cada caixa embaixo com a barrinha dela (🔥 prioridade em cima). Bipou tudo → o cartão inteiro fica verde com ✅ Concluído. Carga sem cliente escolhido mostra os clientes conforme forem bipados.
🔒 Não muda: o palete entra só pelo QR ou pelo ✋ Marcar manualmente; a conta do PA; Finalizar não trava; Carregar por Plano.
🔧 Por dentro: painel_expedicao.html — faltaBiparPorCliente(disp, naCarga, clientesCarga, pedidos) (pura: total = PA + bipados por caixa, 🔥 = prio === 'alta'); confPaRender desenha os cartões; saem CONF_PA_*, confPaUniverso, #conf-pa-cli/#conf-pa-mod. Preview aprovado 9xh7nZi4uQ33oE9W1Nmkj2 v3 ("pode fazer"). Teste: tests/falta-bipar-por-cliente (13).
v2.37.1074
🏢 NOVA CARGA: O CLIENTE MOSTRA AS CAIXAS DELE NO PA E A 🔥 PRIORIDADE; DÁ PRA PÔR MAIS DE UM. Dono em 23/10/2026: "quando selecionar o cliente já aparece as caixas que tem do cliente e a prioridade também que tem que carregar! pode selecionar mais que um cliente".
✅ O que muda (app da Expedição → 🚛 Nova Carga): escolheu o cliente → aparece embaixo cada caixa dele no PA (código, pedido, paletes, caixas), com as marcadas 🔥 prioridade no PCP em cima e de borda vermelha. ➕ Adicionar outro cliente põe mais um; ✕ tira. Total embaixo (clientes · paletes · caixas). A carga nasce com todos os escolhidos (a trava do bipe vale pra todos).
🔒 Não muda: a conta do que está no PA (a régua do Estoque PA); a prioridade continua marcada só no PCP; cliente continua opcional; Puxar da escala, Carregar por Plano, romaneio, o "➕ também vai" no meio da bipagem; a tela de bipar (2ª etapa, se quiser).
🔧 Por dentro: painel_expedicao.html — caixasDoClienteNoPA(disp, pedidos, nome) (pura: agrupa caixa+pedido, prio === 'alta' em cima), NC_CLIENTES / NC_CLI_LISTA, ncRenderClientes, ncTirarCliente, #btn-nc-add-cliente; carga.clientes = NC_CLIENTES.slice(). Preview aprovado GFg6i31b6RrTLdWiXWxvsF ("pode fazer"). Teste: tests/cliente-da-carga-com-caixas (11).
v2.37.1073
📅 APP DO VENDEDOR: NÚMERO DO PEDIDO E DATA DE ENTREGA EM DESTAQUE. Dono em 23/10/2026, com o print da FLOPS (24328 e 24320 em rota, entrega 19/10 e 21/10): "na aba do vendedor quero o numero do pedido e a data que era para ter entregado data da entrega bem destacado".
✅ O que muda (App do Vendedor → Clientes → toca no cliente): no card de cada pedido o número fica grande à esquerda e a data de entrega ganha um quadro grande à direita: vermelho "Era pra entregar" + quantos dias atrasado quando passou da data e não foi entregue; amarelo hoje / amanhã / até 3 dias; azul "faltam N dias"; cinza entregue ou sem data. Quantidade e status descem pra linha de baixo.
🔒 Não muda: a data (é a do pedido), ordem das fases e dos pedidos, status, quantidade, selo "parte já foi no caminhão"; aba Pedidos do vendedor; sistema, PCP e servidor.
🔧 Por dentro: painel_vendedor.html — entregaDestaque(dataEntrega, fase) + classes .ped-n-* no card da lista de clientes. Preview aprovado 1XG5UNUs4R1GZ1UtpegHNE ("pode fazer"). Teste: tests/vendedor-pedido-entrega-destaque (19).
v2.37.1072
🚛 NOVA CARGA: A PLACA SAI DA LISTA DOS CAMINHÕES CADASTRADOS. Dono em 23/10/2026: "no campo placa do caminhão tem que aparecer todos os caminhão que tem na fábrica cadastrado, ele não precisa preencher na mão".
✅ O que muda (app da Expedição → 🚛 Nova Carga, caminhão nosso): o campo Placa do caminhão virou uma lista com os caminhões do Cadastro → Caminhões (placa · apelido, em ordem de placa; inativo fica fora, em manutenção vem marcado). Escolheu o motorista → o caminhão dele já vem marcado; escolheu o caminhão → a capacidade do cadastro é preenchida quando existe.
🔒 Não muda: caminhão De terceiro continua com a placa digitada; Puxar da escala; sistema (Expedição → Nova carga no computador); cadastro de caminhões.
🔧 Por dentro: painel_expedicao.html — #sel-placa (nosso) ao lado do #inp-placa (terceiro), doc('caminhoes').onSnapshot → STATE.caminhoes, opcoesCaminhoes, popularCaminhoes, marcarCaminhaoDoMotorista (casa pela placa limpa), preencherCapacidadeDoCaminhao, placaDaCarga no Iniciar. Preview aprovado EzeQW4Mp4iG1kpbnMCRp6r ("pode fazer": sem "outra placa", ASD9633 fica, só no app). Teste: tests/placa-da-lista-de-caminhoes (9).
v2.37.1071
🚚 APP DA EXPEDIÇÃO SEM "✓ VOLTOU" E COM A ESCALA NUM BOTÃO. Dono em 23/10/2026, com o quadro "Motoristas em rota (7)" na tela (24h, 50h, 83h): "tira esse motorista voltou, não tem necessidade disso" + "esse da escala coloca um botão puxar da escala" + "coloca iniciar carregamento ocupando espaço de 2 botão".
✅ O que muda (app da Expedição, tela inicial): sai o quadro 🚚 Motoristas em rota com o ✓ Voltou; a lista grande 📋 Caminhões da escala hoje sai da tela inicial e vira o botão 📋 Puxar da escala (com o número de caminhões de hoje) — toca, abre a lista, ▶ Iniciar carga igual antes. Nova Carga fica larga, no espaço de 2 botões.
✅ O "em rota" do motorista sai de vez (o Voltou era o único que limpava a marca): some o aviso "saiu numa viagem e ainda não voltou" ao começar uma carga (app, sistema e trocar caminhão da carga), o grupo "Em viagem" na lista de motoristas e, em Logística → Motoristas, a coluna Status e os quadrinhos Disponíveis / Em rota.
🔒 Não muda: Carregar por Plano, Estoque PA, Histórico, Carga aberta, Ficaram pra trás; o que o Iniciar carga da escala faz; a escala/roteiro (status da viagem), app do motorista, checklist; a "Última carga" do motorista continua sendo gravada.
🔧 Por dentro: painel_expedicao.html — sem renderMotoristasEmRota/marcarMotoristaRetornou; renderEscalaDia preenche o #modal-puxar-escala e o número do #btn-puxar-escala; o Finalizar grava só ultimaCarga (sem status:'em_rota'). js/60-motorista-em-rota.js apagado e tirado do app, de js/10-expedicao.js e js/79-corrigir-carga.js; js/09-logistica.js sem selo. Preview aprovado TUDSFK4yVLocbshYupDgzG ("pode fazer, opção 1"). Teste: tests/expedicao-sem-voltou (16).
v2.37.1070
📦 FINALIZAR NÃO DEIXA PALETE PRA TRÁS. Dono em 23/10/2026, com o 24402 NACON · CX 03 dando "Sem paletes para imprimir" e sem nada pra carregar na expedição: o operador montou o palete na Coladeira e tocou ✅ Finalizar sem tocar ✓ Confirmar palete — a CX 03 (991 cx) e a CX 07 (2.154 cx) subiram sem palete.
✅ O que muda (app do operador): com palete montado e sem ✓, o ✅ Finalizar, o 🏁 Fim do turno e o fechar quando outro pedido entra param e mostram "📦 Tem palete sem confirmar": quanto está gravando, quantos paletes já confirmados e quanto falta, e os paletes que vai confirmar pela paletização (a sobra vira palete separado: 2.154 a 2.101/palete = 2.101 + 53). "✓ Confirmar e finalizar" grava já com os paletes; "↩ Voltar" deixa conferir; "Finalizar sem palete" continua existindo.
🔒 Não muda: quem confirma palete por palete não vê aviso nenhum; máquina sem paletização (Slotter, Die Cut, corte e vinco); os outros avisos do Finalizar; sistema, Estoque PA, expedição e etiqueta.
🔧 Por dentro: painel_operador.html — _paletesPorConfirmar (falta = _quantoFaltaLancar − confirmados sem lote), _aplicarPaletesPorConfirmar, _abrirAvisoPaleteSemConfirmar, _portaPaletesSemConfirmar no btn-fim, _popupQtdTurno, btn-turno-finalizar e _abrirJanelaFecharAntes. Preview aprovado B3TCM3M7bRLvgY7KjdYYoQ. Teste: tests/palete-sem-confirmar-no-finalizar.
v2.37.1069
✂️ A POSE DO PEDIDO SEGUE O CADASTRO ATÉ O 1º CORTE. Dono em 23/10/2026, com o 24402 NACON · 04 FRACAO VIGOR na tela: "no cadastro de caixa está 2 poses e no PCP não está duplicando — e isso vai pro operador". O PCP lançou 5.000 chapas às 06:22 com o cadastro em 1 pose; o pedido travou em 1 nessa hora e ficou "−5.000 (50%)", com meta de 5.000 no tablet, mesmo depois do cadastro ir pra 2.
✅ O que muda: pedido com chapa lançada e sem corte apontado acompanha as poses do cadastro da caixa. Salvar a caixa atualiza esses pedidos na hora (e fica na vida do pedido "Poses 1 → 2"). No PCP aparece "5.000 chapas × 2 = 10.000 cx ✓" e o tablet recebe a meta em caixas certas.
⚠ Pedido já cortado e o cadastro mudou de pose: aviso amarelo na linha do PCP "cadastro diz 2 poses · o pedido travou em 1 no 1º corte". Só avisa, a conta não muda.
🔒 Não muda: pedido que já teve corte (Slotter / Corte e Vinco); chapa lançada, livro da chapa, sobra e "Acabou a chapa?"; caixa que não é Corte e Vinco (sempre 1); o cadastro só vale depois de salvo.
🔧 Por dentro: js/01-core.js — jpTemCorteApontado, _jpCaixaDoPedido; posesDoPedido só respeita o posesCongeladoEm (v2.37.1061) depois do 1º corte; jpChapaRegistrar renova p.poses a cada lançamento antes do corte; jpPosesSincronizarComCadastro (carimbo _chapaEditadaEm novo, tela velha não regrava); relAvisoPoses na linha do PCP. js/08-cadastros.js: salvarCaixaModal chama a sincronia e salva os pedidos. Os 3 itens do 24402 (04, 10, 11) foram destravados à mão antes, com backup. Preview aprovado 2ouxB44oXziHUWd29tCuxG ("pode fazer, com o aviso amarelo"). Teste: tests/pose-trava-no-primeiro-corte (23, 2 mutações pegas).
v2.37.1068
↩️ O "REABRIR SLOTTER" APARECE NO TCHETTO 24354. Dono em 23/10/2026, depois da v2.37.1066: "não apareceu o botão / o pedido não foi pro app".
✅ A causa: no TCHETTO 24354 · 27 KETCHUP a decisão "continuar o mesmo pedido" tinha limpado as etapas do pedido; o ✓ da Slotter na tela vinha do quadro do operador, não do pedido. O botão exigia a Slotter "concluída" no pedido e por isso não aparecia. Agora, em pedido já dado por pronto ou Carregado, o botão aparece mesmo sem esse carimbo: ↩️ Reabrir Slotter · cortar 7.289.
🔒 Não muda: pedido em produção com a Slotter aberta continua sem botão (o operador está nele); o resto da v2.37.1066 igual.
🔧 Por dentro: js/01-core.js _reabrirCorteInfo aceita corte sem carimbo quando _pedidoJaDadoPorPronto (a régua do fechamento sem carimbo, v2.37.579). Teste tests/reabrir-slotter-no-carregado (16, com o 24354 lido da MTX; mutação pega).
v2.37.1067
👤 CLIENTE COM CPF (PESSOA FÍSICA). Dono em 23/10/2026: "quero poder fazer cadastro de cliente CPF, hoje só fazemos no CNPJ… tem algum cliente no CPF".
✅ Cadastros → Clientes: em cima do campo do documento tem o botão 🏢 Empresa (CNPJ) / 👤 Pessoa (CPF). Em Pessoa o campo monta o CPF (000.000.000-00), "Razão social" vira Nome completo, o 🔍 Buscar fica "só CNPJ" (a Receita não abre CPF — nome e endereço se digitam à mão) e a Inscrição Estadual pode ficar vazia (a nota sai como não contribuinte). CPF ou CNPJ com dígito errado não salva; CPF repetido barra igual ao CNPJ. Cliente que já existe abre no tipo certo sozinho (11 dígitos = Pessoa).
✅ App do vendedor → Orçamento → 🆕 Cliente novo: o mesmo botão Empresa / Pessoa; cliente novo com CPF entra.
🔒 Não muda: cadastro com CNPJ (começa em Empresa, como sempre); clientes, pedidos e orçamentos que já existem — cliente antigo com número fora do padrão salva como antes; a nota fiscal (o servidor já mandava 11 dígitos como CPF do destinatário).
🔧 Por dentro: js/124-cnpj.js ganha JPDoc (tipo · formatar · cpfValido · cnpjValido · conferir · rotulo); o documento segue no MESMO campo cnpj. js/08-cadastros.js: _cliTipoDoc, máscara, Buscar, trava no salvar (só quando o número foi mexido), clientePorCnpj aceita 11 dígitos. painel_vendedor.html carrega o js/124 (setTipoNovo). Preview aprovado J9xSBYd2oGbd88bBwVJZoC ("pode fazer, com o botão Empresa/Pessoa e o vendedor também aceitando CPF"). Teste: tests/cliente-cpf (37, mutação pega); cliente-cnpj-repetido ajustado ao JPDoc.
v2.37.1066
↩️ PEDIDO CARREGADO COM CHAPA NO CHÃO VOLTA PRA SLOTTER. Dono em 23/10/2026, com o pedido de 10.000 cx (310 × 155 × 180) na tela: "coloco reprogramado e ele não entra no app, coloco material disponível ele volta carregado — teria que ter a opção de reabrir para a Slotter terminar as caixas que ficaram pra trás".
✅ O que muda: com material parado no corte, a janela do pedido (✎) mostra ↩️ Reabrir Slotter · cortar N no lugar do "Reabrir Coladeira · terminar 17" (que era refugo). Reabrir num Carregado devolve o pedido pra produção e ele cai no app do operador. A conta do estoque só passa pra Carregado quem está Pronto / Pronto p/ carregar / Carregado parcial (ou embarcou o pedido inteiro): Reprogramado e Material disponível ficam onde o PCP pôs. O aviso MATERIAL PARADO e o −N (%) da chapa contam só o corte da rodada nova (7.289, não 4.578 / −2.711).
🔒 Não muda: os paletes que saíram continuam saídos; romaneio e estoque iguais; as caixas coladas continuam contando; Reiniciar, Reprogramar, Finalizar com saldo e Excluir iguais; pedido que embarcou inteiro segue sem botão de reabrir.
🔧 Por dentro: js/01-core.js (jpFaltaCortarComChapa, jpReabrirInfoDoModal — corte primeiro; _reabrirCorteInfo e relChapasNota pela rodada) e js/30-saidas-palete.js (spFaltaPassarNaMaquina pela rodada; spMarcarCarregado com a régua da varredura v2.37.765). Teste tests/reabrir-slotter-no-carregado (14). Preview aprovado 9ZDDk8u4aXfHY9soxugZBY ("pode fazer — some o botão da Coladeira 17 e arruma o −2.711 junto").
v2.37.1065
🏷️ A LOGO DO CLIENTE CABE NO QUADRO DA ETIQUETA DO PALETE. Dono em 22/10/2026, com a etiqueta da DEUSA · 23393 na tela: "quero que ela caiba dentro do quadro" — a logo saía com ¼ do quadro e um mar de branco em volta.
✅ A causa: a etiqueta já aparava a margem branca do arquivo da logo, mas desistia calada em 2 casos: logo com o endereço do servidor antigo (KingHost — o navegador não deixa aparar imagem de outro endereço) e pontinho solto perto da borda (segurava o corte lá na ponta). Agora a logo é buscada pelo servidor atual e o corte ignora pontinho solto. A logo cresce até a borda do quadro, com uma folguinha pequena em volta. Vale no sistema e no tablet do operador.
🔒 Não muda: tamanho e posição dos quadros; cliente sem logo segue com o nome escrito; o arquivo da logo no cadastro; QR, quantidades e rodapé.
🔧 Por dentro: js/01-core.js e painel_operador.html (logoCli passa pelo jpArquivoUrl do js/109; aparador com a régua tinta(d,w,h): coluna/linha só conta com ≥3 pixels de tinta). Teste tests/logo-cliente-etiqueta (13, mutação pega). Preview aprovado Afe4mJbFie8YCDkFvAodwM ("pode fazer, com a folguinha pequena em volta").
v2.37.1064
📦 A LINHA DO ESTOQUE PA SALVA COM O NÚMERO DOS PALETES. Dono em 22/10/2026: "já atualizei os PCs da fábrica (F5), pode regravar a linha do PA do 24472" — a linha foi corrigida pra 6.129 no servidor e voltou pra 12.258 em 13 segundos.
✅ A causa: todo PC, ao salvar o estoque (a cada poucos segundos), manda todas as linhas que tem na memória — e a memória ainda tinha o número velho. Agora a linha de pedido paletizado sai com quantidade, paletes e valor contados pelos paletes (a mesma conta que a tela já mostra): todos os PCs mandam o mesmo número.
🔒 Não muda: o que a tela mostra; entrada manual do PA; saídas por palete.
🔧 Por dentro: js/03-estoque.js (estMergeKeyed usa estLinhaViva) · teste palete-verdade-servidor-estoque (17, mutação pega).
v2.37.1063
🧮
AS PERDAS DO OPERADOR CHEGAM NO PCP — FASE 4. Dono em
22/10/2026 (preview aprovado
GkLtpJ9…).
✅ A perda de
ajuste e de
produção que o operador aponta no lançamento passa a vir junto pro sistema: aparece no 📜 Histórico ("perdas N"), na tela de Perdas, no fator
qualidade do OEE e desconta da
sobra de chapa. No 24472: 4 de ajuste + 50 de papel com defeito no Die Cut (qualidade 99,4 %). A mesma perda vista por dois caminhos conta uma vez.
✅
Maq. C Die Cut: ela já aparece em branco em Custos ▸ Custo-hora e no turno por máquina do Cronograma; enquanto o custo-hora dela estiver vazio, o
pós-cálculo avisa "sem custo-hora cadastrado".
🔒
Não muda: nenhum valor de custo-hora ou de turno foi preenchido por mim (é você quem preenche); perdas antigas que ficaram só no tablet não voltam sozinhas.
🔧 Por dentro: js/01-core.js (coletarPerdas lê as perdas do registro; histórico) · js/02-firebase.js (import das perdas, desde a v2.37.1061) · js/77-poscalculo.js (aviso de custo-hora) · teste perdas-no-pcp (9).
v2.37.1062
⏱
TURNO PELO INÍCIO, RELÓGIO SEM RECARIMBO, "SEM CRONO" E CORREÇÃO COM MOTIVO — FASE 3. Dono em
22/10/2026:
"pode fazer … 3: deixa a config como está". Preview aprovado:
GkLtpJ9….
✅
O turno do apontamento é o da hora de INÍCIO, pela config de turno da máquina (Cronograma ▸ turno por máquina; sem ela, o turno geral — mantido como está). O lote do 24472 (14:43 → 16:36 na Coladeira) seria T1, não T2. Antes valia a hora em que o tablet gravava, com corte fixo às 15:00.
✅
Pausa e volta não recarimbam o início: o apontamento leva o horário em que começou de verdade e o tempo produzindo (pausas fora).
✅
"Sem crono": apontamento com menos de 5 min, sem horário ou com início = fim (o 23:57 → 23:58 de 5.324 cx dava 319.440 cx/h). A quantidade vale pro pedido e pro estoque; fica fora de média, meta, OEE, produtividade, eficiência, sugestão de velocidade e pós-cálculo. No histórico a média aparece "—" com o selo.
✅
✏️ qtd e Corrigir palete pedem motivo e gravam
no sistema (não só neste PC): de → para, quem, quando e por quê. Na etapa final de pedido com palete, a correção é no
palete (o apontamento acompanha). Depois de corrigir, produzido, PA e falta são recontados.
🔒
Não muda: o turno dos apontamentos antigos (o recalculado vem ao lado, no dry-run, sem apagar o original); a config de turno; a quantidade de nenhum apontamento.
🔧 Por dentro: js/49-turno-maquina.js (jpTurnoDoInicio) · painel_operador.html (detectarTurno(inicio, maquina), prodInicioPrimeiro/tempoProdMin/semCrono nos registros) · js/01-core.js (jpSemCrono, tempoReal/mediaReal, histórico, eficiência, velocidades; jpGravarQtdRegistro com motivo, jpEditarPeloPalete, jpRecontarDepoisDeEditar) · js/39-oee.js · js/05-produtividade.js · js/77-poscalculo.js · api/src/routes/registros.js (dados.edicoes[] em /qtd e /palete-cx) · teste tempo-turno-edicao (37, 4 mutações pegas).
v2.37.1061
📋
A CHAPA SOMADA, COM HISTÓRICO, E A PERGUNTA "ACABOU A CHAPA?" — FASE 2. Dono em
22/10/2026:
"pode fazer … 2: os 15.000 foram correção". Preview aprovado:
GkLtpJ9….
✅
Todo lançamento de chapa vira uma linha (quanto, total, quem, quando, de onde). Pra
menos é correção e pede o
motivo — sem motivo o número volta. Nada é trocado calado: nem no campo da Carteira, nem na correção da onduladeira, nem no reprogramar.
✅
📜 chapa embaixo da chapa na Carteira: pedido · chapa lançada · cortado · perdas · sobra · finalizado · falta ·
chapa a pedir, os lançamentos e os botões
+ Lançar chapa /
− Corrigir (com motivo). As poses congelam no 1º lançamento.
✅
Tablet: "✂️ Acabou a chapa?" ao encerrar com sobra.
SIM → finaliza com o que lançou; quando o pedido fechar, o restante é
reprogramado sozinho, e a sobra da conta vira
"⚠️ chapa não encontrada" pro PCP conferir (acima de 2 %).
NÃO → passa pro próximo operador: o pedido continua aberto, nada é reprogramado, e o próximo vê "chapa disponível". Fim de turno sem resposta = NÃO.
✅
Avisos (não travam): corte maior que chapa × poses e fechamento maior que o corte viram linha na vida do pedido e aparecem na Carteira. Pedido completo com sobra anota a sobra → estoque de chapa.
🔒
Não muda: o número da chapa que o resto do sistema lê; a tarja de decisão do PCP continua pra quem não respondeu SIM; a chapa antiga não é recontada (o dado antigo vem no dry-run).
🔧 Por dentro: js/01-core.js (saldoChapa, jpChapaRegistrar/jpChapaLancar, jpChapaLancamentos, jpAvisosDeEtapa, jpAoChegarRegistro, relChapaSaldo, jpAbrirSaldoChapa, poses congeladas) · js/02-firebase.js (import leva acabouChapa/perdas/cobreSemPalete; reprograma sozinho no SIM; _jpFecharRodadaDaChapa) · painel_operador.html · painel_onduladeira.html · teste chapa-saldo-acabou (31, 4 mutações pegas).
v2.37.1060
📦
O PALETE É A VERDADE DO PRODUTO PRONTO — FASE 1. Dono em
22/10/2026, com o 24472 NOGUEIRA CX 11 na tela (16.344 cx "concluído" com só 15 paletes × 681 = 10.215):
"pode fazer. 1: sim, pedido sem palete cai na soma com selo". Preview aprovado:
GkLtpJ9….
✅
Produzido, Estoque PA, valor e falta saem de
uma conta só: as caixas dos paletes do pedido. O 24472 CX 11 passa de 16.344 pra
10.215 (falta 1.785), o PA de agora pra
6.129 (9 paletes) e o valor pra
R$ 23.682,46. Apontamento da etapa final
sem palete conta tempo e eficiência da máquina, mas não conta caixa pronta: aparece "⏳ sem palete". Pedido que
nunca teve palete continua pela soma dos apontamentos, com o selo "sem palete".
✅
O estoque não muda mais sozinho: nenhum PC regrava a linha do PA pela soma dos apontamentos a cada atualização (era isso que fazia a correção "voltar"). A tela lê os paletes vivos na hora.
✅
Tablet: o "já feito" chega sempre (não só no reprogramado); aparece "ℹ️ já lançado hoje aqui: X cx"; se o número digitado for ≥ o já lançado hoje, pergunta
"só deste apontamento ou total do dia?" (total → grava a diferença); o palete que chega cobre primeiro o que tinha ficado sem palete; "outro pedido entrou" leva os paletes já confirmados no registro; lote que não cabe nos paletes do cadastro é
bloqueado.
✅
Servidor: lançamento repetido (mesmo pedido, etapa, operador, dia e quantidade com até 2 min de diferença) é guardado
arquivado com o motivo e o tablet avisa ⛔.
🔒
Não muda: paletes, etiquetas, cargas, romaneios e faturas já feitos; nenhum apontamento é apagado; os dados antigos (24472 e os outros) só mudam com a correção do dado, que vem à parte, depois do seu OK.
🔧 Por dentro: js/01-core.js (produtoPronto, qtdProduzida pelos paletes, estLinhaViva, selos) · js/03-estoque.js (reconciliarEstoqueSilencioso sem regravar; render e 🚚 pela linha viva) · js/02-firebase.js (registros, produzidoFinal e aguardandoPaletizacao sempre pro tablet; laudo) · painel_operador.html · api/src/lib/quase-duplicata.js + /api/registros/sync · testes palete-verdade-* (54, mutações pegas).
v2.37.1059
📦 O VENDEDOR SÓ VÊ O ESTOQUE DOS CLIENTES DELE. Dono em 20/10/2026, no login do Armando (a KININO aparecia lá): "quero que ele so tenha acesso aos cliente dele nao da fabrica todas" · "bloqueia no servidor".
✅ Agora: no app do vendedor o 📦 Estoque vira "MEU ESTOQUE", com a faixa 🔒 "Mostrando só os seus clientes": só paletes de cliente cujo cadastro tem ele como vendedor, e os totais contam só esses. O servidor já manda só esses pro celular dele — o resto do estoque nem chega lá. Cliente sem vendedor no cadastro não aparece pra nenhum vendedor. Acesso vencido não lê o estoque.
🔒 Não muda: PCP, Expedição, Operador, Encarregado, Laudo e Onduladeira seguem vendo a fábrica toda; a conta do estoque é a mesma; nada no estoque é mexido. O ADM no "👁 Ver o app de qual vendedor?" vê o estoque daquele vendedor.
🔧 Por dentro: js/81-estoque-pa.js (doVendedor, a régua do "Meus clientes") · api/src/routes/snapshots.js (GET do estoque com crachá de vendedor sai filtrado; crachá vencido = 401) · js/82-estoque-geral.js (modo vendedor). Teste: tests/estoque-so-do-vendedor.
v2.37.1058
📄 O ROMANEIO NÃO LEVA MAIS "JP Micro Ondulados" NO CABEÇALHO. Dono em 20/10/2026, com o romaneio Nº 161 da POWERDENT na tela: "tira do romaneio o jp micro ondulado".
✅ Agora: embaixo de "Romaneio de Entrega" sai só "Expedição · app da expedição" (ou de onde ele saiu). Vale pro romaneio do app da expedição, do sistema e pra 2ª via.
🔒 Não muda: a logo, o número, a data, o cliente, os itens e as assinaturas. O nome continua no cadastro da empresa pros outros documentos.
🔧 Por dentro: js/54-romaneio-doc.js (o papel que o sistema e o app da expedição dividem) — a linha .sub sem empresaNome(). Teste: tests/romaneio-sem-nome-empresa.
v2.37.1057
📱 SAFARI CHEIO NÃO TRAVA MAIS OS APPS. Dono em 20/10/2026, print do iPhone: "o painel do operador ainda não está aparecendo, ele está falando que está sem operador cadastrado" — com os 7 operadores no servidor. O Safari dá pouco espaço por site (e em mtx.torquatro.com.br divide com a Salinas); cheio, ele recusa guardar, e o app desistia ali, antes de desenhar ou de mandar pro servidor.
✅ Agora: a ação vem primeiro (mostrar, mandar pro servidor, entrar) e a cópia no aparelho depois; se o Safari recusar, fica na memória da aba e aparece no rodapé, uma vez, 📦 "A memória deste navegador está cheia" com o Como limpar (iPhone e Mac).
🧰 Consertados: 👷 Operador (lista "Quem é você?", lista ao vivo, login em aparelho novo, chat) · 🚚 Expedição (o bipe agora chega no servidor, abrir/retomar carga) · 🚛 Motorista (viagens do dia) · 💼 Vendedor (pedido de orçamento chega) · 🧻 Bobinas (conferir e dar saída) · 👥 RH e ⏰ Ponto (sincronizar) · login de Compras, Encarregado, Manutenção, Oficina, Almoxarifado e Almox JPE.
🔒 Não muda: telas, senhas, regras de turno e de aparelho, servidor e banco. Com memória livre, tudo igual e sem aviso. Nada guardado no aparelho é apagado.
🔧 Por dentro: js/132-guardar-seguro.js (jpGuardar nunca estoura · jpLer · jpApagar), 1º script de todos os painel_*.html; as gravações que vinham antes de desenhar/enviar/entrar passaram por ele. Preview aprovado N5oF2z8TzB2vLS1qxmNJCz. Teste: tests/safari-cheio-paineis (45, mutações conferidas). Conferido no navegador com o armazenamento cheio: operador com os 7, expedição mandando a carga pro servidor.
v2.37.1056
🚚
SIMULAÇÃO DE CARGA — IDA E VOLTA, SEM PEDIDO. Dono em
18/10/2026:
"preciso falar pro cliente quantas caixas vão, quanto fica o frete, e quantas caixas voltam com o suco dentro, já montadas — sem ter pedido, é só uma simulação pra um futuro pedido". Preview aprovado:
224mBaJqJjBGg7eABggePc (v5).
✅
Onde: 💰 Comercial →
🚚 Simulação de Carga. Escolhe o cliente (puxa a cidade e o km da fábrica), a caixa dele (medida, peso e paletização do cadastro) e o caminhão (baú e capacidade em t) — ou digita tudo. Cidade de saída e de chegada na ida e na volta (ex.: Boracéia → Bauru, Bauru → Americana) com 📍 km pela estrada, e R$ por km de cada lado.
➡️
Ida (caixa plana): paletes × caixas por palete = caixas no caminhão, respeitando espaço e peso; frete da ida ÷ caixas = frete por caixa.
⬅️
Volta (caixa montada com o produto): você põe quanto vai dentro (12 garrafas de 1 L, 1,05 kg cada) e a altura do palete; ele monta as camadas, pesa, e o caminhão volta
cheio: quem manda é o menor entre espaço e peso, e se o peso parou antes sobra lugar pra
1 palete de acerto que encosta no limite.
🎯 Encher o caminhão testa toda altura de palete e fica com a que leva mais caixas. Conta completa:
15 paletes × 150 cx = 2.250 + 1 palete × 44 = 2.294 caixas · 2.294 × 12 = 27.528 garrafas; frete por caixa e por unidade.
📄
PDF pro cliente com a ida, a volta, as contas e o
desenho do caminhão nas duas viagens (só o total do frete, sem o R$/km). 💾
Salvar dá número SIM-0001…; ➡️
Levar pro orçamento abre um orçamento novo do cliente com o resumo do frete na observação.
🔒
Não muda: não cria pedido, não entra na carteira, no PCP nem no estoque; o Planejamento de Carga da Expedição continua igual; o preço do orçamento não muda.
🔧 Por dentro: js/130-simulacao-carga.js (JPSimCarga, puro: chao / camada / calcular / melhorAltura / deCaixa / deCaminhao / svgCaminhao / svgPalete / pdfHTML / textoOrcamento) + a tela #sim-root; palete 1,00 × 1,20, estrado 150 mm e 25 kg, folga de 100 mm pra empilhar 2 (as do Planejamento de Carga); paletização da caixa plana pela plcGeoCaixa (js/22); km pelo JPKmRota (js/95); salva em /api/snapshots/simulacoes_carga por /merge (keyed por id). Perfis: admin, PCP, financeiro, desenvolvimento. Teste: tests/simulacao-carga-ida-volta (47).
v2.37.1055
🚚
O DESENHO DO CAMINHÃO FICA NUM BOTÃO. Dono em
15/10/2026:
"deixa o desenho do caminhão em um botão para abrir" — no monitor largo a planta ocupava a tela inteira. Preview aprovado:
JEQsfbDq14oQeRjjM6HXQ4 (v2).
✅ No 👁 do Histórico e no Carregar Caminhão os números, o aviso do baú e o de palete pulado continuam à vista; o desenho fica atrás de
🚚 Ver o desenho do caminhão (41 paletes · 11 fileiras) e, aberto, tem no máximo 900 px de largura. E o desenho fica na
escala real (pedido do dono: "mais ou menos no formato dos paletes"): antes a largura do baú era esticada e o palete virava um retângulo comprido. No Carregar Caminhão, abriu uma vez, continua aberto a cada bip.
🔒
Não muda: a conta, a sequência, o bip, o romaneio.
🔧 Por dentro: js/129 <details class="jp-cr-desenho"> + JPCargaReal._abertoVivo. Teste: tests/carga-real-dentro-do-caminhao (26).
v2.37.1054
🚚
DENTRO DO CAMINHÃO: A CARGA REAL, MONTADA PELO BIP.
Dono em
15/10/2026:
"quando os paletes forem bipados e o caminhão escolhido, eu sei como está lá dentro a carga … conforme ele for bipado ele aparece em sequência … vejo quantos tem dentro do caminhão e a metragem correta". Preview aprovado:
JEQsfbDq14oQeRjjM6HXQ4 ("empilha quando o baú deixa · junta as cargas do mesmo caminhão no mesmo dia, romaneio separado por cliente · só no sistema").
✅
Agora: o
👁 do
Histórico Cargas abre o quadro
🚚 Dentro do caminhão: a planta (cabine → porta) com cada palete no lugar pela
ordem do bip (número = ordem, ▲ = em cima), paletes, caixas, peso,
metros de baú ocupados (e quanto sobra, quando o caminhão tem as medidas), fileiras, a
sequência do bip (hora, cliente, caixa, pedido · palete, onde ficou) e o aviso de
palete pulado (ex.: 24381 CX M — não entraram P27, P28, P29). As cargas do
mesmo caminhão no mesmo dia aparecem juntas. No
Carregar Caminhão a mesma planta enche a cada bip (● ao vivo).
📏
A arrumação: fileiras a partir da cabine, lado a lado na largura do baú e 2 de altura quando o baú deixa; o tamanho e a altura de cada palete saem da paletização da caixa e das caixas que ele tem (901 cx de 2.250 = 1,20 m). O bip diz quais e em que ordem — o lugar exato é essa arrumação padrão.
⚠
Caso de 14/10 (GCI-2D14 · DAF A): 41 paletes, 11,4 m, 11 fileiras — o DAF A está
sem medida de baú no cadastro; preencha em Cadastros → Caminhões pra ver a sobra.
🔒
Não muda: o bip, a baixa, o romaneio (um por cliente), as cargas gravadas (só leitura), o app do expedidor.
🔧 Por dentro: js/129-carga-real.js (JPCargaReal: doMesmoCaminhao / bauDaPlaca / montar / pulados / svg / html); js/10 _expCargaRealHtml em cargaDetalheHtml e atualizarResumoCarga (#carga-dentro-caminhao); js/22 exporta plcGeoCaixa. Teste: tests/carga-real-dentro-do-caminhao (23) com as 2 cargas reais do GCI-2D14.
v2.37.1053
📅
PLANEJAMENTO DE CARGA: DATAS EM TODO CLIENTE, SÓ O QUE É DA VIAGEM, E A % QUE VAI.
Dono em
14/10/2026:
"está falando de todos os pedidos da ADORA, porém os que estão na data são 32 e estão prontos" · "temos que selecionar as datas de todos os clientes" · "pode colocar a porcentagem do pedido que está indo". Preview aprovado:
NhcgZm1NjpKDg7tdMQPPDq (v2).
🔎
O caso (ADORA, viagem do DAWIS de 15/10): o 24381 de 13/10 pronto no PA (CX M 32 paletes + CX G 6) e o 24432 de 23/10 ainda programado entravam juntos — a regra marcava "o que venceu + a próxima data" — e o PDF dizia "24 de 65". E o PA do 24381 nem achava a data (o pedido está com outro nome de cliente).
✅
Agora: a linha 📅 aparece em
todo cliente (até com uma data só); vem marcado
só o que é até o dia da viagem (atrasado + do dia); se não há nada até lá, a 1ª data seguinte (NACON 23/10, FADA 16/10). Cada data diz
✅ paletes prontos e/ou
🏭 em produção. A data do palete do PA sai do pedido dele (elo forte), não do nome. A
% do que vai aparece no cabeçalho do cliente ("vão 32 de 38 (84%)"), no 👁 Ver e no 🖨️ PDF do plano (por cliente e por caixa); o Ver e o PDF dizem as datas de cada cliente ("📅 13/10").
🔒
Não muda: marcar/desmarcar na mão, planos salvos (reabrem com as datas gravadas), estoque, ⭐, 2º caminhão.
🔧 Por dentro: js/22 plcDatasSelecionadas (≤ dia da viagem; senão a 1ª depois), plcDatasDaCarga (prPal/pdPal; dataDoPed de todos os pedidos), plcDatasHtml (todo cliente), plcDatasTxt no Ver/PDF, % em plcRenderChips / plcImprimirPlano / plcVerPlano. Teste: tests/carga-datas-nome-2-caminhoes (69).
v2.37.1052
📜
O HISTÓRICO DA PRODUÇÃO ABRE EM TELA CHEIA.
Dono em
13/10/2026:
"coloca esse histórico do tamanho da tela e deixa ele como popup". Preview aprovado:
8F5syP8ffuaPtevdXqQyDT (
"resumo no modal, mais novo em cima, arquivado aparece riscado").
🔎
A causa: no 📊 Registrar Produção, a lista do histórico ficava no fim do modal, travada numa caixinha de 240 px. Cabiam uns 2 lançamentos e o resto ficava rolando escondido.
✅
No modal fica só o resumo: quantos lançamentos, o último (dia, turno, máquina, caixas) e o botão
📜 Ver histórico (N) em tela cheia.
✅
O pop-up ocupa a tela toda, com um lançamento por linha (data, turno, máquina, operador, horários, ajuste, produção, quantidade, média, paletes), o mais novo em cima. O arquivado aparece riscado.
✅
Filtro por máquina nos botões do alto (Todas · cada máquina com a contagem). O rodapé soma só o que está valendo no filtro. Esc, × ou clique fora fecha e volta pro Registrar Produção.
🔒
Não muda: ✏️ qtd, × arquivar, 🖨️ Imprimir etiquetas, ✏️ Corrigir palete, 🗑️ Resetar paletes e ⚠️ Lançar ocorrência da diferença funcionam igual, só mudaram de lugar. Contas, registros e app do operador ficam como estão. Sem mudança no servidor.
🔧 Por dentro: js/01 renderHistoricoRegistro escreve o resumo no #r-hist e a tabela no #rh-corpo do novo #modal-historico (sistema.html, z-index 1005, na lista do JP_MODAL_FECHA_NO_FUNDO); _jpHistMaq/jpHistSoma pro filtro e a soma; o filtro fica lembrado no mesmo pedido (window._jpHistFiltro); abrirModalRegistro fecha o pop-up que tenha ficado aberto. CSS .rh-* no css/main.css. Teste: tests/historico-em-tela-cheia (36).
v2.37.1051
↶
O DESFAZER DO MOTORISTA PASSA A VALER TAMBÉM NO ESCRITÓRIO.
Dono em
14/10/2026:
"faz o conserto do desfazer que já chegou no escritório". Preview aprovado:
DRqMqQdQuT9L15a666PGtF (
"pode fazer, 1 sim").
🔎
A causa: o ↶ Desfazer do Roteiro apagava o horário só no celular. O servidor junta o que chega com o que já tinha e não apaga um campo só porque ele não veio: o horário desfeito continuava gravado, voltava pra tela do motorista na leitura seguinte (4 s) e o escritório seguia vendo. O mesmo ao desmarcar 🚚 Saí da fábrica e 🏁 Cheguei na fábrica na viagem da escala.
✅
Agora o desfazer pede pro servidor apagar aquele horário (e o selo 📶 feito sem sinal sai junto). Sem sinal, o pedido espera na fila do celular e apaga quando o sinal voltar; a tela já mostra desfeito.
✅
A Escala mostra o rastro: "↶ desfeito às 10:50 (era 10:42)" na parada, na saída ou na chegada na fábrica, enquanto a etapa continuar desfeita. Refez, o rastro sai da tela (fica guardado no registro).
🔒
Não muda: a pergunta antes de desfazer; a carga bipada (já desfazia certo, com o campo vazio e a hora em "desfeito"); os outros passos e as outras viagens. Sem mudança no servidor nem no banco: ele já sabia apagar, o app só não pedia.
🔧 Por dentro: js/128 JPFilaMot ganhou apagar (caminhos; carimbar(..., sentinela) põe o FieldValue.delete() → unset do /merge; sobrepor tira da tela enquanto não sobe; refez antes de subir → cai; pedaço com ponto não entra); painel_motorista _motApagados (o que sumiu entre antes e depois) + _motRegistrarDesfeito (desfeitos: etapa, tx, era, em, por) em desfazerEtapa, marcarSaida e marcarChegadaFabrica; js/08 escSeloDesfeito. Conferido no navegador com servidor de mentira que aplica merge + unset: com sinal e sem sinal. Teste: tests/motorista-sem-sinal (56).
v2.37.1050
🗓️
PLANEJAMENTO DE CARGA: PUXAR DA ESCALA EM QUADRO, COM BUSCA.
Dono em
14/10/2026:
"puxar da escala já aparece os caminhões pra escolher, a data da escala e o cliente que vai entregar" · "essa lista está confusa, os dias está tudo enrolado — quero um campo de pesquisa dos caminhão" · "o caminhão pode entrar mesmo estando em viagens". Preview aprovado:
RtcrR1jUMrEjroSKbRjgr9.
✅
Agora: no topo do Planejamento de Carga, o quadro
🗓️ Puxar da escala: dias em ordem (Hoje, Amanhã, próximos · antigas sem baixa num grupo à parte, mais nova primeiro),
🔎 busca por caminhão, placa, motorista ou cliente em todos os dias, e um cartão por viagem com os clientes e ✅ paletes no PA / 🏭 em produção / ⬜ sem carga (com carga primeiro). Tocar no cartão escolhe o caminhão, mostra "VIAGEM DE QUI 15/10" e põe no plano os clientes com carga (pergunta antes de trocar um plano montado; viagem que já tem plano salvo abre o plano dela). As 📅 datas de entrega passam a contar a partir do
dia da viagem. O seletor "Caminhão" mostra
todos os caminhões do cadastro, inclusive os que estão em viagem.
🩹
A lista não via a viagem nova: a escala chegava (a cada 8 s), mas a lista do Planejamento só era montada ao abrir a tela — viagem lançada depois só aparecia saindo e voltando. Agora o quadro se redesenha quando a escala atualiza.
🔒
Não muda: a Escala (nada é gravado nela), quem entra (só cliente com carga), a ordem de entrega, 🔥→⭐, planos salvos.
🔧 Por dentro: js/22 plcRenderEscala / plcEscolherViagem / plcPreencherSeletorCam (div #plc-escala), régua das datas pelo dia da viagem em plcDatasSelecionadas; js/08 onAplicar das escalas chama plcRenderEscala. Testes: tests/carga-datas-nome-2-caminhoes (68), plano-carga-viagem-antiga atualizado.
v2.37.1049
📶
APP DO MOTORISTA SEM SINAL NA ESTRADA: CONTINUA DE ONDE PAROU.
Relato de um motorista (13/10/2026):
"no meio da estrada fico sem internet e o app reinicia tudo, como se eu não tivesse feito". Preview aprovado:
RWwhW6LanZ3VPKPbuvex7C (
"pode fazer, 1 sim, 2 sim, 3 sim").
🔎
A causa: cada botão só mandava direto pro servidor. Sem sinal, o 📍 Cheguei da carga se desfazia na hora; na viagem da escala aparecia "Salvo, sincroniza depois", mas o toque ficava só na memória e a leitura seguinte do servidor devolvia a tela pro passo anterior; app fechado no caminho abria vazio.
✅
Agora todo toque vai primeiro pra uma fila no celular e a tela segue. A fila sobe sozinha quando o sinal volta, com a
hora do toque (não a hora em que o sinal voltou). Vale pro Roteiro da escala e pra carga bipada (Cheguei, Entreguei, Devolução, Desfazer, Saí, Cheguei na fábrica, quebra, coletas).
✅ Faixa amarela no topo do app:
"⏳ 2 passos guardados no celular", com botão 🔄 Tentar enviar agora. Passou de
2 horas sem subir → a faixa fica vermelha e o celular vibra/apita uma vez.
✅ A última escala, cargas e entregas que ele viu ficam guardadas no aparelho:
abriu sem sinal, mostra a última viagem que você viu, já no botão certo.
✅
Na Escala e nas Entregas ao vivo, o passo que chegou atrasado ganha o selo
"📶 feito sem sinal às 10:42 · chegou 11:30".
✅ Desfazer um passo que ainda está na fila tira ele de lá:
nunca chega no escritório.
🔒
Não muda: o banco continua sendo a verdade (o celular só segura o que ainda não chegou); ordem do Roteiro, trava do checklist antes de sair, aviso de carga não bipada, checklist do caminhão (já guardava no celular), GPS do Cheguei (vai junto com o passo). Sem API nem banco novos.
🔧 Por dentro: js/128-fila-motorista.js (JPFilaMot: guardar/guardarColeta/drenar/carimbar/sobrepor/idadeMs, puro); painel_motorista: motGravar → 'ok' | 'fila' | 'recusado' (4xx ou coleta já mudada volta como antes), _motOpReg, gravarEntregas agora grava só a viagem tocada, motEscutar (cópia no IndexedDB), renderFilaSemSinal, MOT_FILA.sobrepor no entregas_status e sobreporColetas; js/08 escSeloSemSinal (lê semSinal[etapa] = {tx, feito, subiu}). Teste: tests/motorista-sem-sinal.
v2.37.1048
🚚
PLANEJAMENTO DE CARGA: DATAS DE ENTREGA, NOME NO PALETE, ENCAIXE SOZINHO E ATÉ 2 CAMINHÕES.
Dono em
13/10/2026:
"são datas diferentes e não dá pra saber quais paletes é de cada produto … caberia outro palete porém ele tem que entrar sozinho … até 2 caminhões … quero entregar somente a primeira". Preview aprovado:
NhcgZm1NjpKDg7tdMQPPDq ("pode fazer, foi arrastar palete na planta").
🔎
O caso (NACON 24402): as mesmas caixas em 3 datas (23/10 · 40 paletes, 04/11 · 34, 04/12 · 3) entravam juntas — 75 paletes misturados, e o quadradinho só dizia "P12 1.500".
✅
Agora: (1)
📅 datas — no quadro do cliente com 2+ datas aparecem as datas; vem marcado o que já venceu + a 1ª data futura; desmarcada não entra no plano nem no "fica pra trás" (vira "fora desta viagem"); a mesma caixa em 2 datas vira 2 grupos ("26 TABUAS NACON · 23/10"). (2)
Nome no palete — o quadradinho mostra o número da caixa ("P25
16 1.875") e o toque abre o pop-up "CX NACON 16 KIT FILME PRETO-B" com pedido, entrega, caixas, peso e situação; tirar/devolver e ⭐ ficam no pop-up. (3)
🧩 encaixe sozinho — depois de arrastar/girar palete na planta, o que ficou pra trás e cabe no vão entra sozinho (borda verde 🧩 e o aviso "coube mais N"); 📌 tirado na mão nunca volta sozinho. (4)
🚚 2º caminhão — sobrou palete: "Levar o resto num 2º caminhão" no Fica pra trás; o 2º leva só a sobra do 1º, tem planta e peso dele e, ao salvar, vira um plano próprio ligado ao 1º (romaneio, 👁 Ver, 🖨️ e conferência dele). Máximo 2.
🔒
Não muda: cliente com uma data só, estoque PA, baixa, ⭐ / 🔒 carga fechada / 🧱 batida / 📌, régua de peso e arrumação; plano salvo antes desta versão reabre com todas as datas, como era. Sem API nem banco.
🔧 Por dentro: js/22 plcDatasDaCarga / plcDatasSelecionadas / plcDataToggle (chave do modelo caixaId@data, caixaReal pro romaneio), plcCodigoCurto / plcChipPopup, plcEncaixarSozinho (pilhas novas …|a1), plcMontarPlano (motor por caminhão) + plcCotaDaSobra / plcDescontarCam2 / plcGravarPlano (par / parDe / cota). Teste: tests/carga-datas-nome-2-caminhoes (58).
v2.37.1047
📡
MÁQUINA RODANDO COM O TABLET TRAVADO: O MURAL DIZ RODANDO, O SERVIDOR TIRA DO AJUSTE E O TABLET PERGUNTA O QUE JÁ PASSOU.
Dono em
13/10/2026:
"a maquina esta rodando · esta com estato em ajuste" e
"esse regra tem que valer". Preview aprovado:
2KSxH3wTQnoegVv8u89GVJ ("faz as 3 juntas", "mais de 100").
🔎
A causa (Máq. B Slotter · Arnaldo · 24381 GRS TOYS CX M): 🔧 Ajuste às 21:23, o tablet travou às 21:51 e a Slotter rodou
6.170 peças a 6.234 cx/h com o Mural dizendo
EM AJUSTE. A regra do 🤖 "o app age sozinho" (mais que 20 caixas em 2 min tira do ajuste) rodava
só dentro do tablet — tablet travado, regra parada. E quando ele voltasse, o pedido entrava em produção contando só os últimos 2 min (~208): as outras ~5.960 viravam "ajuste" sem ninguém perguntar.
✅
Agora: (1)
Mural: em ajuste com o sensor contando (mais que 20 desde o 🔧) o cartão diz
RODANDO · pelo sensor e "📡 tablet do Arnaldo sem notícia desde 21:51"; (2)
tablet: se a máquina já tinha rodado
mais de 100 caixas antes de entrar em produção, pergunta
"✅ Tudo entra no pedido · ✏️ digitar quanto foi ajuste · ⏱ só a partir de agora"; sem resposta fica como era e a pergunta volta no ✅ Finalizar; (3)
servidor: a cada leitura do sensor ele aplica a
mesma regra do 🤖 (mesmo botão, mesmos números do ⚙️ Sensor) e põe o pedido em produção mesmo com o tablet travado — o tablet, quando volta,
adota essa produção em vez de abrir outra.
📏
Meta conferida: 9 caixas tinham
100.000 cx/h na Slotter (GRS CX M e CX 09 MARMITINHA, ECOLUBRI CX 02 e CX 04, KIMETAIS CX 07, KININO CX 19 e CX 44, DEVITO CX AZEITONA, REVAL CX BRINQUEDO) — passaram pra
6.000 a pedido do dono.
🔒
Não muda: a régua do 🤖 (20 em 2 min), máquina sem sensor ou com o 🤖 desligado, registros, estoque, paletes, a pergunta da perda do ajuste. Sem tabela nova. 🧰
Luan: pm2 restart jp-cartonagem-api --update-env (sem migration) — sem isso a 1 e a 2 já valem e a 3 (servidor) espera.
🔧 Por dentro: js/38 _rodandoNoAjustePeloSensor + tabletMudo; api lib/sensor-age.js (decidirAjusteParaProducao, janela de 2 min por aparelho, trava morta 4 h, outro pedido rodando = não mexe), chamado solto no POST /api/snapshots/sensor_maquinas/merge; painel_operador _senAjusteRodou / _senMarcoDaResposta / _senAdotarProducaoDoServidor / modal modal-ajuste-rodou, e o 🤖 espera a cópia do servidor ao acordar. Teste: tests/maquina-rodando-tablet-mudo (75 + 5 mutações).
v2.37.1046
🔁
REPROGRAMADO SAI COM A CHAPA DO QUE FALTA CORTAR — E O OPERADOR VÊ O QUE JÁ SAIU.
Dono em
13/10/2026:
"foi feito 10915 e o pedido é de 28000 e está reprogramado e não está no app do operador" · "agora apareceu porém sem quantidade que saiu". Preview aprovado:
UYbKZFEowYx7URzFSan5o4 ("pode fazer, preenche sozinho").
🔎
A causa (GRS TOYS E DOLLS · CX M · 24381): virar
Reprogramado pela Carteira zerava a chapa e pedia "lançar a chapa nova do que falta"
sem dizer quanto faltava — sem chapa o pedido não vai pro operador (sumiu das 18:08 às 18:18), e o PCP lançou
28.000 de novo num pedido que já tinha
10.915 cortadas na Slotter. O app mostrava "28.000 chapas desta rodada · 0 / 28.000", com as 10.915 só numa linha cinza miúda. A conta que o sistema sabia: 28.000 lançadas − 10.915 cortadas =
17.085.
✅
Agora — uma régua só (chapa da rodada nova = lançada − cortada nesta rodada, folga de 10%; faltam cortar = pedido − cortado em todas as rodadas): (1)
Carteira → status Reprogramado: a chapa já vem preenchida com a sobra (17.085) e o pedido vai direto pro operador; a vida diz "🔁 Reprogramado — cortou 10.915 de 28.000 · chapa da rodada nova: 17.085 (28.000 lançadas − 10.915 cortadas)". Sobra dentro da folga: zera como sempre, mas diz "lançar a chapa do que falta cortar (X)". (2)
🔄 Reprogramar · falta (dentro do pedido) sugere a mesma sobra no campo. (3) A decisão
"continuar o mesmo pedido" manda a sobra, não a chapa inteira. (4)
Carteira: chip "🔁 rodada nova · cortou 10.915 · faltam cortar 17.085" e aviso "⚠ X a mais do que falta cortar" ao digitar chapa demais. (5)
App do operador: a linha do cartão diz "✂️ cortou 10.915 · faltam cortar 17.085 · 📋 17.085 chapas desta rodada" (⚠ se lançaram a mais), a barra da Slotter e a meta do Finalizar vão até o que falta cortar (0 / 17.085) e o tempo previsto desconta a rodada anterior (~0h40, não ~0h47).
🔒
Não muda: "caixa pronta" continua contando só na Coladeira/Grampeadeira (0 / 28.000 cx na Carteira); registros, estoque, paletes e ocorrências não são tocados; chapa do corte por rodada e caixa somando tudo (v1039), ⏭ Passar pro próximo turno igual; pedido sem corte se comporta como hoje. Sem API nem banco (sem Luan). O 24381 foi ajustado à mão pra 17.085 a pedido do dono.
🔧 Por dentro: js/01 jpCorteDaRodada / jpChapaSobraPraCortar / jpRegDaRodadaPcp (porte do _regDaRodada) / jpCorteRodadaChip / jpAvisoChapaAMais; bindStatusSelects, reprogramarPedidoParcial, pcpProcessoCelula, bindChapasInputs; js/02 decidirParcial (_chapaFica = sobra); painel_operador _faltaCortarNaRodada, progBarrasOp, _metaDaMinhaEtapa, _linhaCorteRodadaOp, _opTerminoEstimado. Teste: tests/reprogramado-chapa-do-que-falta (44).
v2.37.1045 ATUAL
🧾
FATURAR E EMITIR A NOTA FISCAL DAQUI — ETAPA 1 (homologação).
Dono em
13/10/2026:
"a baixa parou porque eu passei a faturar direto no Sectra" →
"agora eu quero fazer tudo aqui!!! no nosso sistema até fazer nota fiscal!!!" →
"pode fazer". Preview aprovado:
XT8B4Gq…. Levantamento e plano em
cartonagem2-docs/financeiro/.
✅
A aba 💵 Baixa virou 🧾 Faturamento. Cada pedido com romaneio ganhou o botão
🧾 Faturar (no lugar da pré-nota): o mesmo formulário da nota, agora com a
condição de pagamento → duplicatas (28/35/42 vira 3 duplicatas na nota, pela mesma régua do orçamento) e a
forma de pagamento (boleto, PIX…). A nota nasce em rascunho e a tela pergunta se emite.
✅
Emitir · Consultar · Cancelar na SEFAZ na lista 🧾 Notas fiscais (a API tinha as três desde a v2.37.829 e nenhuma tela chamava). Cada nota mostra o status (RASCUNHO → ENVIANDO → AUTORIZADA | REJEITADA com o motivo → CANCELADA), a chave, o protocolo e o DANFE.
✅
Nota AUTORIZADA dá a baixa e cria as parcelas SOZINHA, no servidor — o pedido sai da carteira com o nº da nota gravado e as duplicatas viram parcelas no 📅 Contas & Previsão (valor = total da nota, com IPI, como o boleto; vencimentos contados da data da nota). Vale tanto pelo Emitir quanto pelo Consultar (nota que ficou "em processamento"), e nunca duas vezes. Nota rejeitada não baixa nada. Cancelar na SEFAZ desfaz: o pedido volta (baixa guardada em
baixasDesfeitas) e as parcelas ficam
marcadas como canceladas (filtro 🚫 no Contas & Previsão) — nada se apaga.
✅
"já saiu no Sectra" no lugar do "Dei baixa": pede o nº da NF do Sectra e a data, dá a baixa com esse número e cria as parcelas contadas
da data da nota. É o jeito de limpar os 188 pedidos parados na fila desde agosto.
✅
Uma nota por pedido: o servidor recusa a segunda enquanto a primeira estiver viva (rascunho, enviando ou autorizada); só cancelada/rejeitada libera outra.
✅ A condição de pagamento do pedido (orçamento → cadastro → prazo padrão) passou a ter
uma conta só (
jpCondicaoDoPedido, js/01) — era copiada no darBaixa e no js/64.
🔒
Não muda: estoque PA, paletes, romaneio e app da Expedição (a nota
não baixa estoque); a numeração continua a de HOMOLOGAÇÃO (ambiente 2 — produção segue recusada até virar a chave em 🏢 Empresas); nota gravada antes desta versão sai como saía (sem duplicatas); o "Dei baixa" antigo continua existindo como reserva se o js/64 não carregar.
🛡️
Endurecido pela revisão independente (13/10): o servidor devolve ao blob do Contas & Previsão as parcelas da nota que um PC com cópia velha tentar apagar (e a marca de cancelamento gruda); nota rejeitada não é reemitida se o pedido já ganhou outra nota viva; pedido já baixado por fora (Sectra) não ganha parcelas em dobro; "Consultar" numa nota autorizada refaz a baixa se ela falhou; nota gravada antes da cobrança não emite; descartar rascunho só em rascunho/rejeitada; duplo clique no Emitir não passa (compare-and-set); ↩️ Desfazer num pedido faturado pela NF-e manda cancelar na SEFAZ; "já saiu no Sectra" faz a mesma pergunta de saída parcial e o mesmo aviso de limite do "Dei baixa" e recusa pedido com nota viva; parcela de homologação vem marcada
[HOMOLOGAÇÃO]; limite de crédito e conciliação ignoram parcela cancelada; DANFE com o endereço completo do emissor.
⚠️
Pra sair a 1ª nota de homologação, falta: você — conta no Focus NFe com o certificado A1 da JP e escolher "Focus NFe" em 🏢 Empresas;
Luan —
FOCUS_NFE_TOKEN=… no
.env da API e
pm2 restart jp-cartonagem-api --update-env (sem migration);
contador — conferir alíquotas/CFOP (as 27 UFs estão "não conferidas").
🔧 Por dentro: api/src/lib/parcelas.js (o js/48 num vm — dono único da régua), nfe-cobranca.js (condição → duplicatas, tPag), focus-nfe.js (numero_fatura/duplicatas/formas_pagamento com os nomes da referência do Focus), nfe-pre-nota.js (trava F-10 por pedidos_ids, dados.cobranca, mapNota com chave/protocolo/DANFE), nfe-pos-autorizacao.js (baixa + parcelas sob FOR UPDATE no cc_contas, idempotente; cancelamento marca), nfe-emissao.js (gravarResultado chama a pós-autorização na 1ª autorização), routes/pedidos.js (barreira sticky preserva nfeId/nfeNumero/nfeSerie/nfeChave/nfeOrigem), js/01 (jpCondicaoDoPedido, baixaSectra, fila), js/37 (jpGerarContasReceber(…, opts), conta cancelada fora das listas), js/64 (cobrança no modal, jpNotaEmitir/Consultar/CancelarSefaz, espelho com duplicatas). 9 testes novos (tests/parcelas-no-servidor, nfe-cobranca, focus-nfe-cobranca, pre-nota-cobranca-e-dobro, nfe-pos-autorizacao, nfe-emissao-baixa-automatica, contas-da-nota, baixa-sectra, faturamento-tela), cópia em cartonagem2-docs/financeiro/tests/.
v2.37.1044
🛡️
O ORÇAMENTO NÃO ABRIA (NEM EDITAR, NEM VER / ENVIAR) — E O SISTEMA NÃO PARA MAIS POR ISSO.
Dono em
13/10/2026:
"estou clicando no orçamento e não está abrindo" · "já aconteceu isso uma vez". Preview aprovado:
KwrCs8ptRRXaktXyuGsuh3 ("pode fazer").
🔎
A causa: a entrada v2.37.1043 deste histórico (09:42) entrou com um
</div> a menos. O navegador fechou a janela do changelog no lugar errado e as
21 janelas que vêm depois dela no arquivo (✏️ Editar, 👁️ Ver / Enviar, 🕘 Histórico de preço, 🤝 Registrar aceite, Gerar pedidos, ⚙️ Config, Escala, Caminhão, Caixas do cliente, Vida da caixa…) viraram filhas dela, que fica escondida: o botão roda, a janela "abre", ninguém vê, nenhum erro. É a 4ª vez (10/08, v531 em 24/08, v920 em 24/09 com 6 h parado). Os testes que pegam isso (
tests/modais-filhos-do-body,
modais-nao-presos) moram numa pasta fora do git, e a cópia que fez a 1043 não tinha eles.
✅
Agora: (1) o fechamento que faltava; (2) 🛡️
guarda no boot — ao abrir a página, toda janela que estiver presa dentro de outra volta sozinha pro lugar certo, com aviso no console dizendo quais (se um dia faltar um
</div> de novo, nada para); (3) o
scripts/check-boot.mjs, que roda antes de todo push em toda cópia, passou a acusar modal preso e
barra o push.
🔒
Não muda: nenhuma tela, botão ou número; o reajuste no vendedor (v1043) segue como está; nada na API nem no banco (sem Luan). Se ainda não abrir depois de no ar:
F5 (ou
sistema.html?curar=1).
🔧 Por dentro: bloco inline 🛡️ MODAL PRESO VOLTA PRO BODY no fim do sistema.html (depois do último <script src>, antes da 🩹 cura: querySelectorAll('.modal-bg') → quem não é filho direto do body vai de appendChild pro body); check-boot ganhou modaisPresos() (mesmo parser do teste) em sistema.html e nos painéis com modal. Testes: tests/modal-preso-volta-pro-body.test.mjs (15), modais-filhos-do-body (aceita JP_RAIZ=<worktree>) e modais-nao-presos; check-boot vermelho no HEAD da 1043, verde na 1044.
v2.37.1043
📈
O REAJUSTE DO CLIENTE CHEGA NO APP DO VENDEDOR E NO "APROVAR" DO PCP.
Dono em
13/10/2026:
"os preços foram atualizados e pro vendedor ainda não — quando passamos o aumento pra Tanagra já tem que mudar no sistema pros próximos pedidos. Os que já estão, não mexe." Preview aprovado:
HqgqBPiGA28ghY8ZUpy4RM ("pode fazer, o PCP decide e no orçamento só o aviso").
🔎
A causa: o reajuste (TANGARA +9,5% desde 14/09) mora na ficha do
cliente (js/93), mas o app do vendedor e o botão Aprovar só olhavam o preço do
cadastro da caixa — quem lia o reajuste era só o "+ Novo Pedido" do sistema. Em 21/09 o vendedor lançou a recompra da TANGARA a 1,081 e 1,550 (cadastro puro), o PCP aprovou sem nenhum aviso e o pedido
24247 saiu
R$ 1.912 abaixo do reajustado (6.000 × 1,550 em vez de 1,697 + 10.000 × 1,081 em vez de 1,184). Já entregue —
não foi mexido.
✅
App do vendedor (recompra): a lista de caixas, o preço sugerido e a caixinha "📋 Cadastro" saem com o reajuste do cliente — "📈 Cadastro R$ 1,350 + 9,50% (reajuste desde 14/09/2026) = R$ 1,478/cx", com 📈 na lista; preço digitado abaixo avisa "⚠️ Abaixo do preço com reajuste (R$ 1,478)"; o topo do formulário diz "📈 TANGARA está com reajuste de +9,50% desde 14/09/2026 — os preços abaixo já estão com ele". O item enviado leva
precoReferencia (com reajuste) e
reajustePct;
precoCadastro continua sendo o cadastro puro.
✅
Aprovar do PCP: confere contra o preço reajustado ("⚠️ ABAIXO do preço reajustado (1,184) — 1.030,00 a menos", total "(1.912,00 abaixo do reajustado)"), e
o PCP decide — avisa, não trava. O cartão da recompra, a folha de faturamento e o relatório usam a mesma régua (
pvPrecoRef); recompra já aprovada/recusada não recalcula com o reajuste de hoje. O pedido criado ganha o mesmo carimbo do "+ Novo Pedido" (
precoOrigem cadastro/reajuste/negociado) e entra na linha do tempo do preço.
✅
Orçamento do vendedor: só o aviso "📈 cliente com +9,50% desde 14/09/2026" ao escolher o cliente — o preço sugerido não muda (decisão do dono).
🔒
Não muda: pedido já lançado (o 24247 incluído), o preço do cadastro da caixa (o reajuste continua por cima), orçamento já enviado, o "+ Novo Pedido" do sistema, cliente sem reajuste (tudo igual a antes), o vendedor continua podendo digitar outro preço.
Sem Luan (só arquivos estáticos).
🔧 Por dentro: painel_vendedor.html carrega o js/93-reajuste.js e ganhou precoVendaDaCaixa(cx, cliente) (= precoComReajuste; precoDaCaixa segue cadastro puro porque o js/93 se apoia nele) e itemPedParaEnviar(it); js/09 ganhou pvPrecoRef(p, i) (pendente = reajuste de hoje; aceita/recusada = precoReferencia gravada ou cadastro) e o pvAprovar chama pedidoCarimbarPreco + precoLogRegistrar; js/93: reajusteAvisoOrcamento aceita data-cauda e o ligarNoOrcamento para de procurar depois de 30 s. Teste: tests/reajuste-no-vendedor.test.mjs (29 checagens).
v2.37.1042
📐 O DXF DA FACA ENTRA NO DESENVOLVIMENTO ONDE TUDO COMEÇA — E PODE SER PUXADO DO ORÇAMENTO.
Dono em 13/10/2026: "no desenvolvimento eu não consigo colocar o DXF pra mandar para clicheria, tem que vir daí, é aqui que inicia tudo, mas pode ser puxado do orçamento também".
🔎 Por que não dava: a linha "📐 DXF · anexar" só aparecia na ficha depois de clicar 🔪 Encomendar faca (que só libera com amostra ou arte aprovada); na linha do clichê o único anexo era o PDF; e a 📥 Nova proposta só tinha foto da amostra e do teste. Caixa que já tem faca e só precisa de clichê novo não tinha onde receber o DXF. O servidor, desde a v2.37.1029, já manda arte + DXF pra clicheria quando o DXF existe na ficha — faltava a porta de entrada.
✅ Agora: (1) na 📥 Nova proposta cada caixa tem o botão 📐 DXF da faca (aceita .dxf; sobe junto no 💾 Registrar e entra na ficha como DXF v1); (2) na ficha da caixa a linha 📐 DXF da faca é sempre visível no bloco do desenho — "não anexado · 📐 anexar o DXF", ou "v1 anexado · 🔁 trocar · baixar"; (3) quando a linha do orçamento ligada à caixa já tem o desenho (🎨 Projetar Corte e Vinco ou DXF subido lá) aparece 📥 puxar do orçamento nº X, e o que veio de lá fica escrito "do orçamento nº X"; (4) a janela de 🖨️ Enviar arte pra clicheria já listava o que vai anexado — agora avisa em amarelo quando vai a arte sem a faca (avisa, não trava).
🔒 Não muda: subir o DXF não marca "vai encomendar faca" sozinho; a arte continua sendo o que o cliente aprova; o ✏️ Desenhar a caixa continua gerando o DXF ao mandar a ficha (v1025); proposta criada pelo 📄 Trazer pro desenvolvimento continua recebendo o DXF do orçamento sozinha. Nada na API nem no banco (não precisa do Luan). Preview aprovado: EU4vaLiJGFWgid6omoJPN9.
🔧 Por dentro: js/34 devDxfNova (arquivo em it.dxf até o 💾; devSalvarProposta sobe em desenvolvimento/faca_dxf e manda arquivos:[{tipo:'faca_dxf',versao:1}] — o POST /propostas já gravava em dev_arquivos), devLinhaDxfFicha (chamada nos dois estados do devBlocoDesenho; a antiga devLinhaDxf(i,'faca') saiu do devBlocoFerramentas), devPuxarDxfDoOrcamento (URL do it.faca do js/101 sem subir de novo, ou o texto do cvProjeto.dxf pelo devSubirFacaTexto), devAvisoAnexosFicha na janela da ficha. Teste: tests/dev-dxf-desde-o-inicio.test.mjs (21).
v2.37.1041
📏 A CAIXA DE CORTE E VINCO VAI ABERTA NO PALETE DO ORÇAMENTO — COM O MÓDULO INTEIRO DO CADASTRO.
Dono em 13/10/2026, com a foto do orçamento e a do cadastro: "nessa caixa é corte e vinco e tem que colocar ela aberta como faz no cadastro de caixas … a segunda imagem eu quero o mesmo motor que faz a mesma coisa".
🔎 A causa: o orçamento só tratava a caixa como aberta quando o fechamento estava vazio. Quem escolhia "Sem fechamento (sai do Corte e Vinco pronta)" ganhava a caixa DOBRADA — na foto dele, chapa 891 × 737 na onda BB saía pacote 428 × 737, 4 em caracol × 7 camadas = 700 cx/palete; aberta é 891 × 737, 1 × 15 = 375. E não havia o ✓ pra mandar ao contrário.
✅ Agora o 📦 Paletização do item tem os mesmos controles da seção 8 do cadastro: ✓ 📏 Caixa vai ABERTA (vem marcado sozinho no corte e vinco sem fechamento — e a sua mão manda por cima, nos dois sentidos), Orientação Auto / Normal / Invertida 90° / 🌀 Caracol, 🔒 Amarração entre camadas, 📄 Caixa com espelho, Desconto de aba — e os cartões de resultado (caixa aberta/dobrada, altura do pacote, camadas, lastro, caixas por palete, regra do caminhão, paletes do pedido). O texto azul ficou só com o que a seção 8 não tem: a peça que vai, a base no palete, o overhang usado, o caminhão com a barra % e a conta fechada. Os 3 desenhos do 🖼️ Ver o palete acompanham (peça plana e recorte do DXF quando aberta).
📦 O que você marcar fica no item e desce pro cadastro da caixa quando o orçamento vira pedido (orientação, amarração, espelho, aba, o ✓ aberta) — reabrir o item mostra tudo como estava; o item seguinte nasce limpo.
🔒 Não muda: o motor do palete (js/19) e os desenhos são os mesmos — nenhuma conta nova; caixa maleta (cola/grampo) continua dobrada; o preço do orçamento não lê a paletização; orçamento já gravado não é recalculado sozinho (só ao reabrir o item). Preview aprovado: EU4vaLiJGFWgid6omoJPN9.
🔧 Por dentro: js/08 _orcPalSemDobraAuto (corte e vinco + fechamento '' ou 'sem' = aberta; ORC_SEMDOBRA_MANUAL manda por cima), orcPalSetOrient/ORC_PAL_ORIENT, _orcPalCfgDoItem (aba, orient, amarração, espelho, qtd), _orcPalCards (= palRenderResultsCadastro lendo pp.bruto), _orcPalAjustesLimpar/_orcPalAjustesNaTela, orcPaletizacaoDoItem grava semDobraManual e espelho (vira caixa.espelho no pedido); js/72 _jpPalLastroAuto repassa orient/amarração/foraPadrao/qtdPedido ao palCalcular. Testes: tests/orcamento-caixa-aberta.test.mjs (30) + orcamento-nao-herda-item (caixinha que nasce marcada).
v2.37.1040
✂️ A BARRA DA RODADA NOVA NASCE EM 0 / N. Conferência da v2.37.1039 na tela real (13/10/2026): o cartão do CX 22 na Corte e Vinco vinha sem a barra "✂️ Chapa (Corte e Vinco) · rodada nova 0 / 10.613 (0%)" — a mini-barra se esconde quando o feito é 0 (regra da v2.7.0). O preview aprovado mostra ela zerada; agora, no reprogramado com rodada nova, ela aparece. Só isso mudou.
🔧 Por dentro: painel_operador.html miniBarra(feito, total, rotulo, mostrarVazia); o card manda mostrarVazia só na rodada nova. Teste: tests/reprogramado-volta-pro-corte.test.mjs (27 checagens).
v2.37.1039
✂️
REPROGRAMADO VOLTA PRA CORTE E VINCO · FALTOU CHAPA? PASSA PRO PRÓXIMO TURNO.
Dono em
13/10/2026:
"está com reprogramado, com chapa, não foi finalizado e não está pro operador no app — a Corte e Vinco tem que ver, falta chapa pra cortar" ·
"quando falta chapa para finalizar ele avisa para passar para outro turno" ·
"na troca de turno tem que deixar pra outro operador pegar; hoje ele só dá baixa". Preview aprovado:
F8gxcUMP.
🔎
A causa (KININO · CX 22, nº 24342): o PCP reprogramou às 07:09 com chapa nova de 10.613; a Corte e Vinco somava as chapas de
todas as rodadas (4.460 + 7.150 + 2.938 = 14.548) contra os 10.613, achava que "já cortou tudo" e deixou o Fabricio concluir às 07:15 com 2.938
sem aviso — concluído nesta rodada sai da máquina (v2.37.730) e o pedido sumiu.
✅
App do operador: em pedido reprogramado a barra de chapa do corte conta
só a rodada (registros depois da reprogramação); o cortado antes aparece numa linha cinza ("rodada anterior: 14.548 chapas cortadas · 4.387 cx fechadas"); a linha "📋 chapas" diz "desta rodada" (sem o −4.387 vermelho). A marca de concluído da rodada anterior não enche a barra. O aviso de Finalizar com chapa sobrando diz quantas
chapas sobram e ganhou o botão roxo
⏭ PASSAR PRO PRÓXIMO TURNO como ação principal (a mesma porta do 🏁 Fim do turno: credita o parcial no nome de quem fez, congela o tempo, o pedido fica na lista pro próximo continuar); o "Finalizar · PCP decide" virou a opção menor, pra quando a chapa acabou de verdade. Vale pra toda máquina.
🛠️
Dado: o CX 22 ganhou uma rodada nova no servidor (13/10 08:05, chapa 10.613 mantida, nada apagado) e voltou pra Corte e Vinco na hora.
🔒
Não muda: regra de 08/09 (etapa concluída de verdade sai da máquina); quem reprograma é o PCP; Coladeira/Grampeadeira seguem com "fez X · falta Y" em caixas de todas as rodadas; 🏁 Fim do turno, pausa e prioridade; nenhum registro apagado ou anulado.
Sem Luan.
🔧 Por dentro: painel_operador.html _regDaRodada / _chapasPorRodada (registro é da rodada quando data+fim ≥ _reiniciadoEm; sem hora no mesmo dia = rodada anterior) → chapaProduzida/chapaRodadaAnt/caixaRodadaAnt no _construirPedidosBrutos; progBarrasOp ignora etapas.impressora concluída com reabAtiva < geração; abrirAvisoIncompleto fala em chapa no corte; _passarProProximoTurno = _liberarPgProProximo + sync + autoEnviarRegistros. Teste: tests/reprogramado-volta-pro-corte.test.mjs (24 checagens, 1 mutação).
v2.37.1038
🏷️
ETIQUETA VELHA NÃO VALE PRA PALETE FEITO DEPOIS.
Dono em
12–13/10/2026:
"tudo que é feito na grampeadeira não aparece o aviso para imprimir" →
"pode fazer, coloca a máquina na linha". Preview aprovado:
L9zPxuab.
✅ A Grampeadeira do dia a dia estava certa (a Mayara imprime no tablet e o lote sai marcado). O furo: a marca "já impresso" guardava só o
nº do lote, sem a hora — no DCX PARMEGIANE P (nº 24333) a Grampeadeira fechou o
lote 1 em 09/10 e herdou a etiqueta de 05/10 do lote 1 da Coladeira (anulado). Agora a marca cobre só o palete fechado
até a hora da impressão; o que foi fechado depois volta pro 🖨️ Etiquetas e segura a passagem pra "Pronto p/ carregar". A linha do aviso mostra a
máquina ("09/10/2026 · Grampeadeira · Maycon Torquatro").
🔒
Não muda: o tablet; nº do lote, QR e etiqueta; nenhuma marca apagada; carregado/entregue e lote com mais de 7 dias seguem fora.
Sem Luan.
🔧 Por dentro: js/35 cobertoPelaMarca (registro data+fim ≤ minuto da marca.em; sem hora = cobre, como antes) no pendentes e no promoverProntosComEtiqueta; marcar regrava a hora a cada impressão; carregar junta pela marca mais nova. Medido em 13/10: 253 lotes marcados, 5 com palete depois da marca — só o 24333 entra no aviso (os outros já saíram). Teste: tests/etiqueta-marca-vencida.test.mjs.
v2.37.1037
📦
O LASTRO DIGITADO À MÃO VALE NO CÁLCULO DO PALETE.
Dono em
12/10/2026:
"mantém meu lastro" →
"pode fazer, desenho com aviso". Preview aprovado:
4WPWduC9.
✅ O campo
Lastro marcado como manual só entrava na sugestão escrita: o cálculo da seção 8 usava o encaixe que ele mesmo achava, e a ficha técnica (Plano de Desenvolvimento) e o salvar do cadastro mostravam/gravavam outro número — FK 51896:
8.400 com o seu lastro 1 (350). Agora, com o lastro manual,
caixas por palete = seu lastro × camadas × peças por amarrado no cadastro, na ficha e no que se grava. O card diz "1 · manual (o cálculo acharia 24)" e a legenda do desenho avisa "Desenho = encaixe automático (24 por camada); vale o seu lastro manual: 1".
🔒
Não muda: caixa com lastro automático; altura, camadas, palete; Estoque e Carga (já liam o gravado). ↻ voltar lastro automático continua desfazendo.
Sem Luan.
🔧 Por dentro: js/19 palCalcular — P.lastroManual + P.lastro > 0 → lastro = o manual, lastroAuto = o encaixe (desenho); palAvisoLastroManual nas legendas; js/08 palRenderCadastro manda lastroManual: CX_LASTRO_MANUAL, lastro: cx-lastro. 12 caixas têm lastro manual: só a 51896 e a 51897 mudam na ficha (8.400 → 350, 2.100 → 1.050); em 4 o campo Lastro difere do gravado (01.19 DEUSA, 24 SELECT TANGARA, 43508 FK, CX 220094 BLUE SEA) e o salvar passa a usar o do campo.
v2.37.1036
✂️
CADASTRO DA CAIXA ENTENDE FACA COM VÁRIAS CAIXAS (DXF COM POSES ENCAIXADAS).
Dono em
12/10/2026:
"faz o preview da correção da tela" →
"pode fazer os dois". Preview aprovado:
RuLGcPth.
✅ Com o DXF da faca inteira (FK 51896: 8 caixas em 512,9 × 703), a tela tratava o arquivo todo como "1 caixa". Agora, na seção
Corte e Vinco, aparece "📐 O DXF tem 8 caixas (4 colunas × 2 fileiras) · 1 caixa = 166 × 328 mm"; o
molde de 1 caixa (e a chapa automática ↻) é a faca ÷ 8 = 128,2 × 351,5; o
↻ Pegar do desenho das poses sugere 8; e na
Paletização a caixa que vai aberta é a peça de
1 caixa (166 × 328), não a faca inteira.
🔒
Não muda: DXF de uma caixa só, caixa sem DXF, gerador/Montador, orçamento. Nada grava sozinho; chapa e lastro manuais continuam mandando. As poses continuam só sugeridas (↻).
Sem Luan.
🔧 Por dentro: js/120 jpPosesDaFaca(texto) — a leitura do 3D (uma árvore do js/69 por pose): poses, colunas × fileiras e o tamanho de 1 caixa, guardado por texto; js/23c cvDxfTexto(); js/23 cvRenderCadastro — com DXF 1×1 sem molde manual: molde de 1 caixa = folha ÷ (col × fil), custo/caixa e área ÷ caixas do DXF, aviso azul, CV_ULTIMO.posesDxf/pecaDxf, refaz a dica das poses; js/08 cxPosesDoDxfAtual (lê o DXF da caixa aberta, nunca o de antes) em cxPosesDoDesenho e palPecaAberta. Testado no cadastro de verdade, rodando local contra os cadastros reais: 51896, 51897, CX 25, CX 22 e TCHETTO 03 (as 3 últimas iguais a antes).
v2.37.1035
🔁 O AVISO DE DEVOLUÇÃO PARA DE VOLTAR QUANDO O PEDIDO JÁ FOI DECIDIDO.
A devolução registrada pelo motorista no app avisava de novo a cada vez que o sistema abria, mesmo com o pedido já Entregue (caso EMPORIO PRIME, "sem ajudante"). Agora: pedido Entregue ou com o status mudado depois da devolução não avisa mais, e cada devolução avisa uma vez por PC. O histórico do pedido continua mostrando o 🔁.
🔧 Por dentro: js/08 jpSincronizarEntregasMotorista — "decidido" = statusOp entregue ou evento de status no histórico depois do devolvidoEm; o "já avisei" vai pro localStorage (jp_devolucoes_avisadas) com a hora da devolução na chave. Teste: tests/aviso-devolucao-decidida.test.mjs
v2.37.1034
💳 A OC QUE VAI PRO FINANCEIRO LEVA O FORNECEDOR, O CLIENTE E O PIX — E O FORNECEDOR INFORMA O PIX DELE NO PORTAL.
O "💰 Mandar pro financeiro" do app de Compras passa a dizer pra quem o serviço foi fechado (fornecedor e cliente) e traz o bloco PAGAMENTO: valor, forma, chave PIX e favorecido. A linha "condição: a combinar" saiu; a condição só aparece quando tem prazo de verdade. Sem emoji, então acabou o "�". Fornecedor sem PIX: o comprador é avisado antes de mandar e pode cadastrar ali mesmo (grava na ficha do fornecedor). No portal do fornecedor, quem está sem PIX vê "💳 Seus dados pra pagamento" e informa a chave; ela entra na ficha só se ela estiver sem forma de pagamento (trocar é com o comprador).
🧰 Luan: precisa do pm2 restart (rota nova do PIX no portal e a trava no salvar do cadastro de fornecedores).
🔧 Por dentro: painel_compras msgOC(o, md, fin) + ocBlocoPagamentoTexto (lê do js/123 JPPag.daOC) + ocAvisoSemPix; api POST /api/portal-forn/:token/pagamento + lib lerPixDoPortal/aplicarPixDoPortal/preservarPagamentoDoPortal (no salvar de fornecedores: cópia velha não apaga o PIX do portal; tirar depois, tira). Testado contra Postgres (9 casos, inclusive o PUT de cópia velha). Preview: https://claude.ai/artifact/KrYT28fyDUeTaJK3JQi2fS
v2.37.1033
🩹 "MANDAR PRO FORNECEDOR": ESCREVER NA OBSERVAÇÃO NÃO TIRA MAIS O CURSOR DA CAIXA.
A cada letra a janela se redesenhava pra prévia da ficha acompanhar o texto, e isso recriava a caixa de observação: o cursor saía dela. Agora a prévia continua acompanhando e o cursor fica onde está; o que foi digitado enquanto a ficha carregava também não se perde. Sem Luan.
🔧 Por dentro: js/34 devRenderEncomendaMontar lê o texto que está na caixa AGORA e devolve o foco e a seleção depois de redesenhar (mesmo defeito da busca, v2.37.769). Teste tests/dev-mandar-ficha-nao-abre-vazia.test.mjs.
v2.37.1032
🧊
3D: FACA COM VÁRIAS CAIXAS MONTA A POSE SEM DEFEITO.
Dono em
12/10/2026:
"faz o preview do recorte da pose" →
"pode fazer". Preview aprovado:
UsMdMmrM.
✅ Na FK 51896 o 3D montava justo a pose com um pedacinho de corte faltando (uma aba de 1.226 mm² grudada na sobra entre as fileiras, virando um painel de 8.849) — saía com um pedaço pendurado. Agora ele compara as caixas da faca e monta a que bate com as outras: a peça sai limpa (uma luva com a aba de trava por dentro).
⚠️ O corte faltando está no DXF da 51896 — vale conferir antes de mandar pra facaria.
🔒
Não muda: faca, DXF, chapa, preço; FK 51897 e faca de uma caixa só ficam iguais.
Sem Luan.
🔧 Por dentro: js/120 poseLimpa(J, ents, base, esp) — com mais painel solto que painel na caixa, acha as poses (uma árvore do js/69 por pose), compara as áreas ordenadas de cada uma com a mediana e devolve uma base na pose mais parecida (painel de área mais próxima da base de antes); chamada na tela e na foto do mockup.
v2.37.1031
🧊
3D: FACA COM VÁRIAS CAIXAS MOSTRA UMA CAIXA SÓ — SEM PEDAÇO SOBRANDO.
Dono em
12/10/2026:
"arruma a faca da FK 51896 — é uma faca com várias caixas, não precisa sobrar" ·
"são 8 poses" →
"pode fazer". Preview aprovado:
WyxvzQj2.
✅ A faca com as poses encaixadas (FK 51896: 8 caixas; FK 51897: 6) aparecia no 3D com uma caixa montada e as outras como dezenas de pedaços soltos por cima. Agora mostra uma caixa, e o cabeçalho diz
"1 de 8 caixas da faca".
🔒
Não muda: faca, DXF, poses do cadastro, chapa, preço. Caixa com 1 ou 2 pedaços soltos de verdade (tampa separada) continua mostrando eles.
Sem Luan.
🔧 Por dentro: js/120 modeloDoJs69 — mais painel solto que painel na caixa = as outras poses (o js/69 acha cada pose como uma árvore separada; 51896 = 79 painéis em 8 árvores de 10) → saem do modelo, model.poses no cabeçalho (pintarConta). Testado com o sistema local contra os cadastros reais.
v2.37.1030
💲 PORTAL DO FORNECEDOR: A CLICHERIA/FACARIA INFORMA O VALOR, ANEXA O ORÇAMENTO E A NOTA — E VÊ O COMPROVANTE.
A ficha que vai pra clicheria e pra facaria (e-mail e WhatsApp) leva o link com o nome do cliente (ex.: "💲 KININO · CX M · Clichê CL-0271 — informar valor, orçamento e nota"). Ele abre o portal do fornecedor, com todas as encomendas de clichê e faca dele separadas por cliente. Ali ele baixa os arquivos, informa o valor e a previsão, e anexa o orçamento (PDF) e a nota (PDF ou XML), que pode mandar depois. Cai sozinho na OC: o valor entra se ela estava vazia (se o comprador já tinha digitado, aparecem os dois com "usar o do fornecedor"), com o selo 💲 na lista e aviso com som no app de Compras. O comprovante de pagamento se anexa na OC (app de Compras) ou no Financeiro → Compras pra pagar (📎 pago com comprovante). Aí o fornecedor vê "✅ Pago" embaixo do valor da nota, e fica no 📒 registro de pagamentos da ficha do fornecedor. O cartão do desenvolvimento mostra o valor, os anexos e o pago.
🧰 Luan: precisa do pm2 restart (página e rota novas). O link só sai na ficha com o SISTEMA_URL do servidor preenchido (o mesmo dos avisos do Desenvolvimento).
🔧 Por dentro: fornecedor.html (pública, sem api-config) + api routes/portal-fornecedor.js (aberta antes do login, token de 24 hex no snapshot portal_fornecedor, freio de 30 erros/min) + lib/portal-fornecedor.js (ocDoFornecedor pela id e nome exato, só clichê/faca; projetarEncomenda sem o preço do cliente; aplicarInformado não sobrescreve o valor do comprador; tipoDoArquivo confere o conteúdo); o salvar de ordens_compra preserva o envio do fornecedor e o comprovante (preservarInformado); a OC do desenvolvimento leva fornecedorId/devItemId. Testado contra Postgres de verdade (16 casos). Preview: https://claude.ai/artifact/6DZknyVmRpnQiw6wkStdVL
v2.37.1029
📤 CLICHERIA E FACARIA: CADA UMA COM OS SEUS E-MAILS — E O ARQUIVO VAI ANEXADO.
Na ficha do fornecedor (Cadastros ▸ Fornecedores), quem vende clichê ganha 🖼️ E-mails da clicheria e quem vende faca ganha 🔪 E-mails da facaria. Cabe mais de um, separado por vírgula. Sem e-mail do setor, vale o e-mail geral. No desenvolvimento, o 🖨️ Enviar arte pra clicheria reserva o número e já abre a janela de mandar. A lista mostra primeiro os fornecedores de clichê (ou de faca), diz pra quais e-mails vai (dá pra desmarcar) e o que vai anexado: no clichê a arte e o DXF da faca, na faca o DXF. O WhatsApp continua com a ficha e os links. A etiqueta do clichê fica no botão 🏷️.
🧰 Luan: precisa do pm2 restart — o anexo e os e-mails do setor saem do servidor. Antes do restart a janela funciona, mas o e-mail sai como antes (e-mail geral, arquivo por link).
🔧 Por dentro: api lib/ficha-encomenda emailsDoSetor/destinatarios (a tela só DESMARCA: endereço fora do cadastro é descartado); lib/smtp corpoMime (multipart/mixed) + Resend attachments; rota anexosDaFicha (clichê: arte + faca_dxf; faca: faca_dxf), lê do disco e, se sumiu, de arquivos_upload; só /api/uploads, sem ..; até 10 MB anexado. js/125 emailsCliche/emailsFaca + sincSetor; js/34 devBlocoDestinos, devReservarFerramenta abre a janela. Preview: https://claude.ai/artifact/TTS5ToAFSgy8rpFZdmuVDa
v2.37.1028
📋 VIROU PEDIDO NO DESENVOLVIMENTO → O CADASTRO DA CAIXA NASCE PRONTO.
Ao lançar o pedido, a caixa vai pro cadastro com o que foi desenhado no ✏️: o desenho da faca (o DXF que foi pra facaria), as cores, o ajuste da arte e do 3D, a chapa, o roteiro e a paletização, além do nome, do cliente e da arte aprovada. O nº do clichê e da faca agora é o número reservado (ex.: 263-A); antes ia o preço (ex.: 450) nesse campo. Caixa que já está no cadastro (recompra) mostra cada mudança "de → para" antes de gravar, como sempre. Pelo orçamento convertido também: caixa nova leva o desenho do desenvolvimento, e a que já existia só ganha o que estava vazio.
🩹 "📤 Mandar pro fornecedor" abria em branco desde a v2.37.475 (um pedaço da montagem tinha sido apagado). Voltou: lista de fornecedores, a ficha, WhatsApp e e-mail. Sem Luan.
🔧 Por dentro: js/34 devCamposDoDesenho (lista FECHADA de campos do dados.caixaRascunho + DXF/arte/números da ficha; preço, velocidade e fiscal ficam de fora), devDiffDoDesenho no "de → para" da recompra, devCaixaNovaDoItem sem o preço no nº; js/08 orcParaPedidoConfirmar lê a ficha (devItemDoServidor) antes do forEach; js/34 devBlocoPedidoCompra(i, null, …) + erro de montagem escrito na janela. Preview: https://claude.ai/artifact/71zEq4pFXm1QtF3cf9dqDn
v2.37.1027
🧊 3D: 230 DE 235 CAIXAS SEM NENHUMA ABA DENTRO DE OUTRA — AS 16 QUE FALTAVAM ARRUMADAS.
Dono em 11/10/2026: "arruma as 18 que faltam, me mostra como ficou".
✅ Base na aba do fundo (KININO CX 03, NACON 03/07/14, FK 04141/31459/31644/35597/43508/44959/46670/50591): as abas de dentro do fundo ficavam do lado de FORA da base, aparecendo por baixo — agora ficam por dentro, encostadas.
✅ Bandejas DCX (ROYAL PARMA P/G, PARMEGIANE P/G): duas ou três abas colando na mesma parede iam pro mesmo lugar — agora cada uma encosta na anterior.
⚠️ Não é aba: FK 51896 e 51897 — o desenho manual da faca (8 poses) não fecha os painéis e vira 69 peças soltas; precisa refazer o desenho. FK 51900, GRANJA HATTO ACESSÓRIO e FARMASI 05 não têm faca/medida pro 3D.
Conferido ANTES de publicar: o sistema com o código novo rodando contra os 235 cadastros reais; nenhuma caixa que estava certa mudou pra pior. Sem Luan.
🔧 Por dentro: js/118 dentroDaBase (aba de andar 0 paralela à base e em cima dela vai pro lado do miolo), laps um de cada vez na ordem das dobras (mede de novo entre um e outro), e a ordem das dobras DESLIZA a aba até ficar livre de todo paralelo (antes desistia na segunda peça).
v2.37.1026
🧊 3D: CONFERIDO EM TODAS AS 235 CAIXAS ATIVAS — 217 SEM NENHUMA ABA DENTRO DE OUTRA (NA v2.37.1018 ERAM QUASE NENHUMA).
A v2.37.1024 tirava a parede da linha de abas e o fundo de quem tem a aba como base ficou com as abas de dentro atravessando a aba do fundo (1,2 mm em quase todas as KININO) — voltou. Abas que dobram JUNTAS e se encontram de frente no mesmo andar: a de fora sobe por cima, a de dentro desce pro miolo. Conferência feita com o sistema rodando o código novo contra os cadastros reais, comparada com a v2.37.1018: nenhuma caixa piorou; as 18 que ainda têm algum cruzamento já tinham na v2.37.1018 (faca com várias poses, DCX ROYAL PARMA/PARMEGIANE, caixas quase quadradas com base na aba). Sem Luan.
🔧 Por dentro: js/120 andares — a parede deitada volta pra linha (classifica junto, por posição); js/118 pelaOrdemDasDobras — ordem (fim da dobra, ordem na faca), vale dentro do mesmo andar, empate de frente: andar ≥ 1 pra fora, andar 0 pro miolo; trava de "piora".
v2.37.1025
📐 DESENVOLVIMENTO: O DESENHO DA CAIXA VEM SOZINHO — E SE EDITA AQUI DENTRO.
O cartão da caixa pedia pra anexar o DXF na mão mesmo quando ela já tinha sido desenhada no orçamento. Agora o desenho aparece no cartão (📐 Faca desenhada · veio do orçamento Nº …), com a miniatura, ⬇ DXF, ⬇ PDF e 🧊 Ver em 3D. O ✏️ abrir o desenho (ou ✏️ Desenhar a caixa, quando não teve orçamento) abre o mesmo cadastro de caixa — material, onda, medida, Montador, arrumar a arte, cores, palete e 3D — e o 💾 Salvar no desenvolvimento grava na ficha, sem criar a caixa no cadastro ainda. A faca vira o arquivo da facaria e da clicheria sozinha; o "📤 mandar a ficha" já leva ela. DXF do ArtiosCAD anexado à mão continua mandando. Sem Luan.
🔧 Por dentro: js/34 devDesenhoDoItem (rascunho > DXF anexado > linha do orçamento > cadastro > medida da ficha), devAbrirDesenhador/devSalvarDesenho (dados.caixaRascunho + dados.desenhoFaca com hash — só sobe faca nova quando mudou); js/08 CX_DESTINO_DEV: o salvar do modal entrega o dados e sai antes do CAIXAS; js/106 jpFacaArquivoDaCaixa. Preview: https://claude.ai/artifact/71zEq4pFXm1QtF3cf9dqDn
v2.37.1024
🧊 3D: CAIXA QUASE QUADRADA — AS ABAS DE FACES OPOSTAS FICAM NO MESMO ANDAR.
Na CX 03 (280 × 280) e na CX 09 KININO o 3D decidia "aba de fora" pelo tamanho da aba; com a compensação os tamanhos ficam quase iguais (281/283/285) e ele punha abas vizinhas no mesmo andar — uma dentro da outra no canto da tampa. Agora, na linha de abas da maleta, elas alternam em volta da caixa: frente e trás num andar, laterais no outro; o tamanho só escolhe qual par vai por fora. Sem Luan.
🔧 Por dentro: js/120 andares — só aba (sem filho) entra na linha; linha com 3+ abas classifica pela POSIÇÃO em volta da caixa (paridade do x da dobradiça, nas duas linhas juntas), o par de abas maiores vai pro andar 1; linha com 2 abas segue a régua do tamanho.
v2.37.1023
🩹 3D: A ORDEM DAS DOBRAS SÓ MEXE EM ABA ATRAVESSADA DE VERDADE — E NUNCA EMPURRA PRA DENTRO DE OUTRA.
A v2.37.1022 não resolveu a CX 03 e a CX 09 KININO: a causa real era um toque de 0,1 mm entre abas que a regra da v2.37.1021 tratava como atravessada, empurrando a aba uma espessura inteira — pra dentro da aba de fora. Agora ela só age acima de 0,3 mm, só se todas as peças cruzadas estiverem do mesmo lado, e desiste se o empurrão criar outro cruzamento. Sem Luan.
🔧 Por dentro: js/118 pelaOrdemDasDobras — limiar 0,3 mm (o mesmo da conferência), lado por candidato (presa entre dois = não anda), teste de "piora" com todos os paralelos antes de gravar o dz.
v2.37.1022
🩹 3D: A ORDEM DAS DOBRAS NÃO BRIGA MAIS COM O LAP E AS ABAS DE FORA.
Conferência depois da v2.37.1021 (todas as caixas KININO com arte, no ar): a CX 22 ficou certa, mas a CX 03 e a CX 09 (que estavam limpas) ganharam abas 3 mm dentro de outras — a regra nova empurrava as abas de dentro por cima das de fora. Agora a ordem das dobras só decide entre painéis sem andar; o lap (por dentro) e as abas de fora (por fora) seguem a regra da v2.37.1019. Sem Luan.
🔧 Por dentro: js/118 pelaOrdemDasDobras ignora candidato com cola ou stack > 0.
v2.37.1021
🧊 3D: NENHUMA ABA ATRAVESSA OUTRA — NO CORTE E VINCO VALE A ORDEM DAS DOBRAS.
Dono em 11/10/2026: "deu certo, o lap ficou por dentro — o conserto tem que ser em todas as abas" → "é a CX 22, arruma pela ordem das dobras".
✅ Conferidas as 22 caixas da KININO com arte: 21 já sem nenhuma aba dentro de outra depois da v2.37.1019/1020. Na CX 22 (corte e vinco 340 × 240 × 115) dois painéis de 240 × 185 atravessavam o fundo em 1,8 mm — agora o painel que dobra depois fica encostado por cima do que já estava (do lado de onde ele veio), e as abas presas nele vão junto.
🔒 Não muda: caixa sem aba atravessada (só age quando há chapa dentro de chapa); faca, DXF, chapa, preço. Sem Luan.
🔧 Por dentro: js/118 pelaOrdemDasDobras no fim do encostar — painéis sem andar (nem lap, nem aba de fora) em ordem de phase[1]; cada um que cruza (faixas de espessura > 0,05 mm) um paralelo que dobrou antes anda pro lado em que já está a maior parte dele (empate: longe do miolo); vale pra painel com filhos — o setFold passa o deslocamento do pai (offF) pro bendMap da dobradiça do filho. Lab com a faca da CX 22: P2/P6 −1,8 mm → encostados por dentro do fundo (fundo 0…−3, P2/P6 −3…−6).
v2.37.1020
🧊
3D: A CAIXA MONTA NA MEDIDA INTERNA DO CADASTRO — A COMPENSAÇÃO É DESCONTADA NA DOBRA E O VÃO DA TAMPA FECHA.
Dono em
11/10/2026 (caixa 34983 FK GRUPO, BB):
"tem um vão aberto na caixa, usa as compensações para deixar esse vão menor" →
"faz a compensação". Preview aprovado:
3cNmi7qb.
✅ Os painéis da faca já trazem a compensação (129 = 125 + 4, 131 = 125 + 6) e o 3D dobrava no vinco: a 34983 montava
130 mm por dentro na largura (cadastro: 125) e
610 no comprimento (605). Agora o 3D mede as paredes e desconta a sobra numa dobra só por eixo:
125 × 605 por dentro, e o vão entre as abas da tampa caiu de
6,7 pra 1,8 mm (medido). Vale no 3D do cadastro, no arrumador, no mockup do Plano e no Desenvolvimento — onde vem a medida interna.
🔒
Não muda: faca, DXF, chapa, compensações gravadas, preço; caixa sem medida interna e o Montador ficam como estavam.
Sem Luan.
🔧 Por dentro: js/118 comerCompensacao(C) antes do encostar — o tubo = painel do lap + paredes ligadas por dobra paralela à dele; monta a 100%, mede a distância entre as faces retas de dentro de cada par de paredes opostas, compara com a medida mais próxima de C.interna e grava recuo na parede mais funda da árvore daquele eixo (0,2 mm < sobra ≤ 2 espessuras); no setFold a dobradiça dela anda recuo pro lado do pai, junto com a dobra. js/120 internaDe(o) (de o.interna ou do texto o.medidas) no contexto da tela e da foto; js/08 mockup e js/121 foto passam a mandar medidas. Lab com a faca da 34983: parede oposta −141,6…−133,5 → −136,6…−128,6; P8 −308 → −303,1.
v2.37.1019
🧊
3D: O LAP FICA POR DENTRO E AS ABAS DE FORA POR FORA · 🎨 ARRUMAR NA FACA COM A ARTE QUE ACABOU DE ESCOLHER.
Dono em
11/10/2026 (caixa 34983 FK GRUPO, onda BB):
"está dizendo que não tem arte anexada, mas tem um arquivo" ·
"o lap está do lado de fora, tem que estar do lado de dentro" ·
"as abas na mesma lógica, porém do lado de fora" →
"pode publicar". Preview aprovado:
3cNmi7qb.
✅
Cadastro da caixa → 6.5 Arte → 🎨 Arrumar na faca abre com o PDF/.ai escolhido e ainda "aguardando envio" (antes só olhava a arte já salva e dizia "não tem arte anexada"). A arte em si continua subindo no
Salvar Caixa.
✅
3D da caixa (cadastro, arrumador, plano, mockup, Montador): o lap fica
inteiro por dentro, encostado na lateral onde cola (antes: 3,5 mm pra fora na BB, 1,5 mm na B). As abas de fechamento de fora ficam
por fora, encostadas nas de dentro. A aba da face comprida com compensação diferente (611 × 609) não atravessa mais as abas das laterais.
🔒
Não muda: faca, DXF, chapa, compensações gravadas, preço — só o desenho 3D.
Sem Luan.
🔧 Por dentro: js/118 encostar() — monta a caixa a 100%, mede a parte reta de cada painel (normal da espessura), e anda o lap (p.cola) pro lado do miolo da parede paralela que ele cobre / a aba de andar ≥ 1 por fora das de andar menor; o deslocamento entra na ESPESSURA antes do bendMap (a v981 somava no Z depois da dobra, que a 90° é o comprimento da aba). Só folha, trava em 4 espessuras. js/118 slotted: COLA com cola:true. js/120 andares: aba de fora = acima do meio entre a maior e a menor (antes "≥ maior − 0,5"). js/08 cxArrumarArte: cópia da caixa com a arte pendente em data:. Medido num lab com a faca da 34983: lap −311,5…−305,5 → −302,2…−296,4 (lateral −308…−302,2).
v2.37.1018
📋
FICHA DO OPERADOR: TODA MÁQUINA CADASTRADA TEM ABA (A DIE CUT APARECE).
Dono em
10/10/2026:
"aqui está faltando a máquina die cut — se eu adicionar uma máquina ela tem que aparecer aqui" →
"pode fazer". Preview aprovado:
Ko6MXnoX.
✅ Em
Análises → Ficha do Operador, depois das 4 de fábrica, vem uma aba pra cada máquina
ativa do cadastro (Die Cut, Facão…), mesmo sem apontamento no dia (aba com 0 e "Nenhum apontamento nessa máquina nesse período"). Máquina nova cadastrada aparece sozinha.
🔒
Não muda: números, eficiência, perdas e "Fechar turno" das outras máquinas. Máquina
pausada no cadastro fica escondida — só aparece no dia em que tiver apontamento.
Sem Luan.
🔧 Por dentro: js/28 foTabsList + foMaqsCadastradas (maqProcAtivas, mesma regra do cronLanesTurno do js/21). Antes a aba de máquina cadastrada só nascia de um registro no dia. Teste novo tests/ficha-maquinas-cadastradas.test.mjs (6).
v2.37.1017
📆
PLANEJAMENTO: ATRASADO ENTRA NA SEGUNDA, NOS DIAS, PELA VELOCIDADE DA MÁQUINA — E O DIA A DIA VIROU GRADE.
Dono em
10/10/2026 (sábado):
"quero os que estão atrasados a partir de segunda-feira, dentro dos dias, em cima da velocidade da máquina" ·
"é dessa forma que eu quero que apareça no planejamento, por dias da semana" →
"pode fazer, pode tirar as barras". Preview aprovado:
Ag7tvnJ2.
✅
Sábado e domingo: a semana atual não tem mais dia útil, então os quadros andam uma semana —
SEMANA 1 (segunda a sexta, com os atrasados dentro) e
SEMANA 2. Acabou o "0 dias úteis · CABE 0,0 h · sem turno cadastrado" com 16 atrasados. Aviso azul em cima: "Hoje é sábado… a conta começa na segunda".
✅
Quem já venceu vai na frente da fila da previsão (do mais velho pro mais novo, mesmo "esperando programação"), logo depois da 🔥 prioridade alta. Vale no Planejamento e nos dias futuros do 🏭 Cronograma — a fila é uma só.
✅
DIA A DIA em grade: uma por semana, os dias em colunas e as máquinas em linhas. Em cada quadrinho os pedidos na ordem: hora de início, cliente e caixa, quantidade, horas de máquina e
venceu dd/mm (fundo vermelho). Em cima, horas usadas / horas do turno e o %; embaixo, o total do dia. Mostra as
2 semanas inteiras. Clique no pedido abre o pedido; clique no dia abre o 🏭 Cronograma. As barras saíram daqui (continuam no Cronograma).
🔒
Não muda: velocidade, turno, ajuste e almoço (a conta é a do cronograma); o plano de HOJE congelado e o nº do pedido no tablet; nenhum pedido muda de status/data/máquina. De segunda a sexta os quadros das semanas são os de sempre.
Sem Luan.
🔧 Por dentro: js/83 semanas() com pulou (semana corrente sem dia útil → +7 dias, rótulos SEMANA 1/2); previsaoDiaria vai até semanas()[1].fim; quadroDias reescrito como grade (.pls-grade, horas produtivas do minutosProdutivos; o apontamento fora do plano de hoje entra no quadrinho com ✔/▶). js/21 cronFilaPrevisao reordena estável: 🔥 alta → vencido por data → ordem de sempre (o cronPedidosElegiveis do plano de hoje não muda). Medido na carteira de 10/10: FK 23357, FK 23359 e NACON 24166 saíram do dia 21/10 pra segunda 12/10. Teste novo tests/planejamento-atrasado-na-segunda.test.cjs (36, com 5 mutações); os 2 testes antigos do Planejamento atualizados pra grade e fila nova.
v2.37.1016
📥
LER A FICHA EM PDF QUE O CLIENTE DEVOLVEU.
Dono em
09/10/2026:
"faz o ler pdf devolvido" →
"pode fazer". Preview aprovado:
CYTyvbVf.
✅
Cadastros → Clientes → ✏️ → seção 🚚 Recebimento → 📥 Ler PDF devolvido: escolha o PDF que o cliente mandou de volta e as respostas
preenchem os campos (com borda azul) + a faixa "Veio do PDF: N respostas · preenchido por …".
Não salva sozinho — confira e clique em Salvar; aí o selo vira "✓ preenchido por Carla (PDF)" e o "🚚 sem perfil" some.
✅ O que o cliente não respondeu fica como estava. PDF impresso/fotografado, ficha em branco ou PDF que não é a nossa ficha: avisa e não mexe em nada. Ficha de
outro cliente (CNPJ diferente): pergunta antes.
🔒
Não muda: o PDF não fica guardado (só as respostas), login/senha do portal nunca vêm do PDF.
Sem Luan.
🔧 Por dentro: js/126 JPFichaReceb.lerPdf(PDFLib, bytes) → {tipo: ok|vazio|sem_campos|outro, respostas, perfil, quem, data, cnpj, nome} (rádio lido pelo /V nome ou texto ou pelo /AS do botão marcado — cada leitor grava de um jeito); o gerar passou a etiquetar o arquivo (keywords: jp-ficha-receb cnpj=…). js/08 crecLerPdfEscolher/crecLerPdfArquivo (pdf-lib 1.17.1 do cdnjs carregado só no clique; base = o que está na tela; CREC_PDF_QUEM vira o preenchidoPor no Salvar; _crecPdfLimpar na próxima abertura). Conferido com um PDF preenchido de verdade: 5 campos preenchidos, doca que já estava ficou, selo só muda ao salvar.
v2.37.1015
🚚
PEDIDO NOVO SÓ COM A FICHA DE RECEBIMENTO + 🔗 LINK PRO CLIENTE PREENCHER.
Dono em
09/10/2026:
"faz o sistema bloquear o pedido sem ficha" ·
"pode até fazer um link para mandar para o cliente igual ao de aprovação" →
"pode fazer, trava em 15 dias, admin libera". Preview aprovado:
Dp9KPqJJ.
✅ Cliente
🚚 sem perfil não ganha
pedido novo em: + Novo Pedido · 📋 Várias caixas · 📋 Gerar caixas + pedidos do orçamento · ✅ Aprovar pedido do vendedor · 🚀 Lançar do Desenvolvimento.
Até 23/10 o aviso aparece e deixa
Salvar mesmo assim (fica anotado no pedido);
a partir de 24/10/2026 barra. Só
admin vê
🔓 Liberar só este pedido, com motivo — fica na vida do pedido.
✅ O aviso traz
🔗 Copiar link pro cliente,
📄 PDF pro cliente e
✏️ Preencher agora (abre o cadastro na seção 🚚). Cliente que nem tem cadastro também cai na trava.
✅ Aceite automático (vendedor ou link de aprovação) de cliente sem ficha, depois de 24/10: o orçamento fica
✅ aceito esperando com a linha "🚚 Falta a ficha de recebimento". Importar do Sectra
não barra: o resumo lista os clientes do relatório sem ficha.
✅
Cadastros → Clientes → 🔗 Link pro cliente (e no app do vendedor, embaixo do 🚚 Recebimento): copia o link e abre o WhatsApp do cliente com a mensagem pronta. O cliente responde no celular (as mesmas perguntas do PDF), toca em
Enviar respostas e em até 30 s a resposta cai na seção 🚚 — "✓ preenchido por Carla (pelo link)" — e o pedido fica liberado. Abrir o link de novo mostra o que já respondeu, pra corrigir.
🔒
Não muda: pedido que já está na carteira, saldo reprogramado (-R), parcial, dei baixa do resto, editar pedido, lixeira. Login e senha do portal não são pedidos no link. 🧰
Luan: pm2 restart da API pra rota nova do link (
/api/portal-receb) — sem isso a trava funciona, mas o link mostra "a ficha ainda não está liberada".
🔧 Por dentro: js/127-trava-recebimento.js novo — JP_TRAVA_RECEB_DESDE, jpTravaRecebimento(nome) (casa pelo clienteNomeOficial; dois com o mesmo nome = não casa), jpTravaRecebPorta(nome, refazer) (modal; o passe vale só na 2ª passada do handler), jpTravaRecebCarimbar(pedido) (travaRecebLiberada + evento), jpTravaRecebAutoPode (aceite automático, sem modal), jpRecebLinkCliente e jpLerFichasDoCliente (lê o ledger recebimento_respostas a cada 30 s; idempotente por recebLinkAplicadoEm). Portas: js/01 btn-salvar (só sem id) e import do Sectra (só lista), js/86 lancar, js/08 orcParaPedidoConfirmar/orcAutoConverterDoAceite, js/09 pvAprovar, js/34 devConfirmarPedido. Rota pública api/src/routes/portal-recebimento.js (antes do authMiddleware, igual ao portal-orc: token ≥16 + freio por IP, devolve o perfil sem portalAcesso, grava no ledger com a linha travada). Página ficha.html (sem api-config, sem SW). js/126 ganhou paraPerfil/juntarAoPerfil/paraRespostas — a conversão resposta → cliente.recebimento num lugar só (serve também pro PDF devolvido). Conferido: conversão ida e volta, fases antes/depois de 24/10, ledger → cadastro (idempotente, correção sobrescreve), modal no navegador (aviso salva com evento; trava sem admin sem 🔓; admin exige motivo) e a ficha.html contra uma API de teste (mostra o perfil, envia só o respondido).
v2.37.1014
📦
O ✕ DO ESTOQUE PA NÃO BARRA MAIS PRODUÇÃO NOVA.
Dono em
09/10/2026:
"a caixa 24333 cx p foi produzida mas não entrou no estoque" →
"pode fazer, só a linha no livro basta". Preview aprovado:
X7x8Hro7.
A causa: o 24333 · DCX · PARMEGIANE P foi reiniciado em 07/10 e tirado do PA pelo
✕ "remover sem expedir", que marca o pedido pra caixa
nunca mais voltar. Ele foi refeito (Corte/Vinco 08/10, Grampeadeira 09/10 — 2 paletes, 2.064 cx) e os paletes novos ficaram de fora, sem aviso.
✅ Palete do processo final fechado
depois da hora do ✕ é produção nova: entra no Estoque PA sozinho (PCP, Estoque → Caixas e app da Expedição), a marca do ✕ é desfeita e o livro de movimentos diz
"produção nova depois do ✕ de dd/mm", uma vez.
🔒
Não muda: o ✕ continua tirando a caixa na hora; sem produção nova ela não volta (nem por aparelho velho reenviando os mesmos paletes); carregado/entregue continua fora; registro anulado não conta.
Sem Luan.
🔧 Por dentro: js/03-estoque.js — _estMarcadoParaNaoVoltar pergunta _estProducaoDepoisDoX(pid, marca) (palete confirmado, de registro não anulado, da etapa do processoFinalDe, com loteEm — senão enviadoEm — mais novo que marca.em) e chama _estDesfazerMarca(pid, 'producao_nova'); _estObsVoltaDoX põe o texto no livro (js/03 e js/02 adicionarPedidoAoEstoquePA). Marca sem hora continua valendo. Teste tests/estoque-x-nao-barra-producao-nova.test.mjs (18 checagens, 4 mutações) com o caso real; os 10 testes antigos do estoque seguem verdes.
v2.37.1013
📄
FICHA "COMO VOCÊ RECEBE" EM PDF PRO CLIENTE PREENCHER E DEVOLVER.
Dono em
09/10/2026, com a foto da lista de clientes (🚚 sem perfil):
"quero um pdf para mandar para cliente preencher e devolver para nós" →
"pode fazer os dois". Preview aprovado:
VHR9bHYp.
✅
Cadastros → Clientes → 📄 PDF pro cliente (do lado do nome): baixa a ficha de 2 páginas A4 com o
nome e o CNPJ do cliente no topo. Os campos são
digitáveis — o cliente abre no celular ou no computador, clica, preenche, salva e devolve por WhatsApp ou e-mail (ou imprime e preenche à caneta).
✅ As perguntas são as mesmas do 🚚 perfil de recebimento (A agendamento e horário · B acesso e veículo · C descarga · D paletes · E conferência e documentos · F quem recebe), em palavras de cliente.
🔒
Não muda: o cadastro do cliente e o formulário do vendedor. Quando a ficha voltar, alguém passa as respostas pra seção 🚚 do cliente — o "sem perfil" some ao salvar. Login e senha do portal
não vão no papel (só o link).
Sem Luan.
🔧 Por dentro: js/126-ficha-recebimento-pdf.js novo — JPFichaReceb.gerar(jsPDF, {nome,cnpj}) (AcroForm do jsPDF 2.5.1 já carregado; sem cliente = versão em branco com Empresa/CNPJ digitáveis) e baixar(cliente). O nome de cada campo do PDF é a chave do perfil do js/67 (agendamento, veiculoMax, janelaDias.seg…) — pronto pra etapa do 📥 ler o PDF devolvido. Botão _crecBotaoFichaPdf/cliFichaRecebPdf (js/08). Conferido gerando o PDF no node e lendo de volta (57 campos; caixinhas nascem desmarcadas — o jsPDF nascia com /V /On).
v2.37.1012
🏪
UMA FICHA SÓ DE FORNECEDOR — COMPLETA E COM 🔎 BUSCAR — NO SISTEMA E NO APP DE COMPRAS.
Dono em
09/10/2026, com a foto do ✏️ Editar Fornecedor da DAL COLOR:
"todos os cadastros dos fornecedores têm que ter a mesma tela completa e têm que aparecer onde precisa; esse é o cadastro principal, a busca tem que estar aí também" →
"pode fazer, sim nas duas". Preview aprovado:
Qi8aw1ip.
A causa: as duas telas já gravavam na
mesma lista, mas cada uma mostrava uma parte — o sistema sem Buscar/razão social/endereço/CEP/WhatsApp; o app com "o que fornece" em texto livre (Pedido de Compra e Almoxarifado não achavam pela categoria) e sem Ativo (desativado no sistema seguia na OC).
✅
Cadastros → 🏪 Fornecedores → ✏️ e
App JP Compras → 🏪 Fornecedores → ✏️: a mesma ficha, na mesma ordem — CNPJ com
🔎 Buscar (BrasilAPI e, se cair, CNPJ.ws) · Quem é (razão social, nome, nome curto) · O que ele fornece (os botões) · Onde fica (endereço, cidade, UF, CEP) · Falar com ele (contato, telefone, WhatsApp, e-mail) · Pagar (condição + 💳) · Observação e Ativo.
✅ O
"o que fornece" de texto que o app gravava (ex.:
Lápis) aparece na
Observação — marque o botão certo e salve. ✅ Na OC do app,
WhatsApp vazio + Telefone celular = manda pelo telefone; e o
Ativo vale nos dois.
🔒
Não muda: a lista de fornecedores (ninguém some, nada apagado), a tabela/busca/filtro do sistema, 💳 pagamento, 🌳 FSC (continua só no sistema, logo depois da Observação), Excluir.
Sem Luan.
🔧 Por dentro: js/125-forn-ficha.js novo — JPFornFicha.html(prefixo) / preencher / ler / buscar + ativo(f) (aceita ativo:false e status:'inativo'), whatsapp(f) (campo ou celular: DDD + 9 + 8 dígitos), rotulos(f), e o CAT (as mesmas 17 chaves, agora num lugar só — o js/33 lê dele). js/33 abrirModalForn/salvarForn e painel_compras limparFormFornecedor/editarFornecedor/salvar/OC pela ficha; o buscarCnpjFornecedor do app saiu (a busca mora na ficha). Testes tests/forn-ficha-unica.test.mjs (28) + tests/cnpj-reserva.test.mjs (20); no navegador: modal do sistema aberto com FSC, DAL COLOR buscada pelo CNPJ.ws, app com inativo fora da OC e celular como WhatsApp, ficha no celular (375 px) sem rolar de lado.
v2.37.1011
🔍
BUSCAR CNPJ DA EMPRESA QUE FATURA TAMBÉM COM RESERVA.
Dono em
09/10/2026, depois de testar a v1010 no fornecedor (
"veio pelo CNPJ.ws"):
"coloca a reserva no Faturamento também" →
"pode fazer". Preview aprovado:
XCHKYjC7.
✅
Orçamentos → 🏢 Faturar por → 🏢 Empresas → ✏️ → 🔍 Buscar: se o BrasilAPI der erro (com o CNPJ da JP deu 500 em 09/10), pergunta ao
CNPJ.ws e preenche os mesmos campos — inclusive
CNAE,
código IBGE do município e o tipo da rua — e a conferência
"📋 Bate com a Receita" do Simples/MEI também funciona pela reserva. A linha verde diz
"(pelo CNPJ.ws)".
🔒
Não muda: com o BrasilAPI no ar, tudo igual; o que a Receita não traz não apaga o digitado; o regime não muda sozinho (a tela só avisa); a Inscrição Estadual continua sendo à mão; nada salva sem o Salvar.
Sem Luan.
💡 Achado: o cadastro inicial da JP tem a razão social antiga (
…EIRELI EPP) e
SIMPONI; a Receita diz
…LTDA e
SIMPIONI — 🔍 Buscar + Salvar corrige.
🔧 Por dentro: jpEmpresaBuscarCnpj (js/64) chama JPCnpj.buscar; o deCnpjWs (js/124) passou a traduzir também tipo_logradouro, atividade_principal.id, cidade.ibge_id e simples ("Sim"/"Não" → true/false; sem dado → null, data de opção só se optante). Teste tests/cnpj-reserva.test.mjs (20 checagens) + consulta real da JP no navegador: veio pelo CNPJ.ws, Simples = não.
v2.37.1010
🔎
BUSCAR CNPJ NÃO PARA MAIS QUANDO O BRASILAPI CAI.
Dono em
09/10/2026, com a foto do cadastro da DAL COLOR (62.257.282/0001-64) no app de Compras:
"verifica por que está dando erro 500" →
"faz o preview do segundo serviço" →
"pode fazer". Preview aprovado:
NEzqXBPs.
A causa: o 500 vinha do
BrasilAPI (o serviço grátis que o 🔎 Buscar consulta), não do sistema — a fonte da Receita dele respondia 503 pra CNPJ que ele ainda não tinha guardado.
✅
App JP Compras → 🏪 Fornecedores → 🔎 Buscar e
Cadastros → Clientes → CNPJ → 🔎 Buscar: pergunta ao BrasilAPI como antes; se ele der erro, a linha avisa
"BrasilAPI fora, tentando outro serviço…" e pergunta ao
CNPJ.ws, que preenche os mesmos campos — a linha verde diz
"(pelo CNPJ.ws)". CNPJ que não existe continua dizendo "não encontrado" (sem perguntar ao outro); os dois fora → "tenta de novo em alguns minutos ou preenche à mão".
🔒
Não muda: com o BrasilAPI no ar, tudo igual; os mesmos campos e as mesmas regras (no fornecedor, nome e telefone digitados ficam); e-mail não é preenchido; aviso de CNPJ repetido e km do cliente iguais. A busca de CNPJ dos
dados da empresa (Faturamento) segue só no BrasilAPI.
Sem Luan.
🔧 Por dentro: js/124-cnpj.js novo — JPCnpj.buscar(cnpj, aoTrocar) devolve {d, fonte} com d no formato do BrasilAPI (deCnpjWs traduz o publica.cnpj.ws; 3 consultas/min grátis, CORS liberado pro nosso domínio). Chamado por buscarDadosCNPJ (js/08) e buscarCnpjFornecedor (painel_compras). Teste tests/cnpj-reserva.test.mjs (14 checagens) + consulta real da DAL COLOR no navegador: veio pelo CNPJ.ws.
v2.37.1009
💳
COMO PAGAR O FORNECEDOR (PIX / BOLETO / TED) + VALOR DO CLICHÊ NO PEDIDO DE COMPRA.
Dono em
09/10/2026:
"no caso de clichê tem que ter um campo para digitar o valor que vai para o comprador fazer o pagamento" e
"o fornecedor tem que ter todos os dados para o pagamento — se for boleto coloca boleto, se for pix ter o campo para adicionar o pix — e isso já sai no pedido de compra e também o financeiro ver" →
"pode fazer e subir". Preview aprovado:
WjYxeSd7.
✅
Cadastros → Fornecedores (e o 🏪 Fornecedores do app JP Compras): parte nova
💳 Dados pra pagamento — Forma (PIX / Boleto / Transferência / A combinar); PIX pede tipo da chave, chave e favorecido; Transferência pede banco, agência, conta. A condição (28 dd) continua onde estava.
✅
Custos → 🛒 Pedidos de Compra: em Clichê e Faca, ao lado do cliente, o campo
💰 valor a pagar (opcional; sem ele o item avisa "sem valor informado"). Embaixo do fornecedor aparece
💳 Pagamento do cadastro, com
trocar só neste pedido. Na hora de mandar, a forma e a condição são copiadas pro pedido.
✅
Sai no papel: Imprimir, PDF e WhatsApp do pedido ganham a parte
PAGAMENTO (valor + forma + chave/banco + condição); no app JP Compras, o PDF da ordem e o "💰 Mandar pro financeiro" também.
✅
App JP Compras: o cartão mostra o valor informado, a forma de pagamento e
📋 copiar chave; o valor do clichê já vem preenchido como valor da compra; ao comprar, o pagamento do fornecedor escolhido vai pra ordem (o trocado à mão por quem pediu fica).
✅
Financeiro → 📅 Contas & Previsão: bloco novo
🛒 Compras pra pagar — ordens já COMPRADAS, com valor, forma (PIX/BOLETO), chave com 📋 e
✅ pago. Sai quando marca pago ou quando a compra chega e é lançada.
🔒
Não muda: tinta e peças seguem com o preço cadastrado; o comprador continua podendo pôr o valor final; o "🏪 A pagar para fornecedores" e os números de cima das Contas iguais; fornecedor antigo não perde nada (só fica sem os dados novos até alguém preencher). Boleto: só marcado (anexar o arquivo fica pra depois).
Sem Luan.
🔧 Por dentro: js/123-pagamento.js JPPag (campos/ler/limpar/linha/daOC/acharFornecedor) — fornecedor.pagamento e ordem.pagamento (+origem 'fornecedor'|'pedido'), ordem.condPag, item valorInformado, carimbo ordem.pagoEm/pagoPor; js/13 _pcPagHtml/_pcPagDoForm/_pcValorItem/_pcPagTxt/_pcRotTotal, jpOcsParaPagar/jpOcMarcarPaga (escritor único jpAtualizarOrdemCompra); js/33 modal; js/37 blocoComprasPagar; painel_compras ocPagCopia/ocPagTexto/copiarChavePix. Teste tests/pagamento-fornecedor.test.mjs (51 checagens).
v2.37.1008
🔎
PRODUTO DO ESTOQUE: DIGITAR E IR APARECENDO, POR PEDAÇOS.
Dono em
09/10/2026, com a foto do Pedido de Compra:
"azul dh 29111 — posso digitar qualquer um, azul, dh ou 2911, ele já aparece" →
"pode fazer, só na categoria e no almoxarifado também". Preview aprovado:
6LwNGWop.
✅
Custos → 🛒 Pedidos de Compra → Produto (do estoque): a lista fechada virou campo de digitar. A cada letra a lista filtra; cada palavra pode estar em qualquer lugar e em qualquer ordem (
29111 dh acha
AZUL DH 29111), sem ligar pra maiúscula nem acento. Procura no nome, no fornecedor e no nome da tabela do fornecedor. Cada linha mostra o mesmo de antes (quanto tem, mínimo, já pedido, ⚠️ abaixo do mínimo). Clique ou ↑ ↓ Enter escolhe;
— outro (digitar na mão) — fica sempre no fim.
✅
Almoxarifado: a busca da tela do Almoxarifado · Cartonagem e a dos apps JP Almoxarifado (estoque, entrada, vincular, escolher peça) acham do mesmo jeito, por pedaços.
🔒
Não muda: a lista continua só da categoria escolhida em "O que comprar"; Qtd sugerida, 💰 preço cadastrado, Pôr na lista e Mandar pro comprador iguais; os outros campos de busca do sistema seguem como estavam. Nenhum dado é alterado.
Sem Luan.
🔧 Por dentro: js/84 JPBusca.casa(texto, consulta) + opções porPalavras e sempre no montar/ligarSelect (opção data-sempre="1"); js/13 ligarSelect('pc-item', {porPalavras:true}) no fim do renderCcPedidosCompra, opções com data-t/data-s/data-k; js/31 acItensFiltrados; painel_almoxarifado casaPalavras(); painel_almoxarifado_jpe renderEstoque. Teste tests/busca-por-pedacos.test.mjs (33 checagens).
v2.37.1007
🔑
ACESSO DO ADMINISTRADOR NO APP DO MOTORISTA (COM BAIXA NUM BOTÃO) E CADA MOTORISTA CRIA O PRÓPRIO PIN.
Dono em
08/10/2026, depois da v1005 (atrasada em vermelho):
"tem entregas desde o começo; quero entrar com login de adm igual faço no vendedor — mesmo eles tendo a senha deles eu entro com adm e dou baixa na entrega com um botão" e
"agora quero que eles escolham a senha deles igual os expedidores" →
"pode fazer". Preview aprovado:
Uxf4pRco.
✅
App JP Motorista → tela de entrada → 🔑 Acesso do administrador: seu e-mail e senha do sistema (o servidor confere; só perfil admin entra) → escolhe o motorista (a lista mostra 🔴 quantas atrasadas cada um tem) → o app dele com a faixa
👁 MODO ADMINISTRADOR e
🔁 Trocar de motorista.
✅
Baixa do adm: botão
✅ Dar baixa (adm) em toda viagem com entrega faltando (hoje ou atrasada) e, em cima,
✅ Dar baixa em todas as atrasadas (N). Antes de gravar, pergunta na tela (Sim / Cancelar). A baixa marca as paradas como entregues com a hora de agora, mantém o que o motorista já tinha feito, e fica escrito
"✍️ baixa pelo adm Maycon · 08/10 10:20". A viagem atrasada some do app.
✅
PIN do motorista: o PIN que o PCP cadastra virou
provisório. No primeiro acesso o app pede
🔑 Crie a SUA senha e
🔁 Digite de novo (o mesmo PIN do PCP é recusado). Em
PCP → Cadastros → Motoristas entra a coluna
Senha (🔒 senha dele / 🔑 provisória) e o ✏️ Editar não mostra mais o PIN: vazio = mantém; digitar um PIN novo = reset (ele cria outro no próximo acesso).
🔒
Não muda: o celular do motorista não tem o botão de baixa; quem já está logado só cria o PIN quando sair e entrar de novo; a sessão do adm não fica salva no aparelho (fechou = volta pra entrada); escala do sistema, cargas e romaneio.
Sem Luan (usa a mesma conferência de senha do app do vendedor).
🔧 Por dentro: js/115 JPRoteiro.baixaAdm (carimbo entregas_status.entregas[v].baixaAdm); painel_motorista: fazerLoginMestre (POST /api/auth/vendedor-mestre, o token devolvido é descartado), escolherMotoristaMestre, aplicarFaixaMestre, perguntarBaixaAdm/confirmarBaixaAdm, PIN em 3 modos (processarPin, carimbo pinTrocadoEm no cadastro motoristas), iniciarDados liga as escutas uma vez só; js/09 PIN opcional no editar + reset apaga o carimbo + coluna Senha. Teste tests/motorista-adm-e-senha.test.mjs (25 checagens).
v2.37.1006
➕ ACRESCENTAR NUM ROMANEIO QUE JÁ EXISTE — MESMO NÚMERO, MESMA DATA.
Dono em 07/10/2026: "quero que adicione no que já existe, porque ele já é adicionado e já foi pro cliente" + "mas pode deixar a função disponível". Preview aprovado antes de codar.
📋 O caso: o romaneio Nº 119 (TANGARA, carga de 29/09) saiu às 10:03 com 3 produtos. A CX 15 tinha sido tirada da carga às 09:54 e voltou às 13:04 — o dono corrigiu o papel à mão e mandou assim pro cliente. Emitir um número novo criaria dois números pra mesma entrega.
✅ No quadro do 📄 Romaneio da carga entrou uma terceira saída, em verde: ➕ Acrescentar ao Nº 119, dizendo o que entrou depois (CX 15 · 7 pal · 5.033 cx). Ela só aparece quando falta item de verdade — em carga certa o quadro sai idêntico ao de antes.
🔒 Número e data não mudam, e nada é apagado: fica registrado o que entrou, por quem e quando. O papel passa a dizer isso, numa linha pequena — embaixo da tabela e dentro do canhoto, que é a parte que fica com o cliente. É ela que explica a diferença pro que está escrito à mão na via dele.
✅ Só acrescenta item que NÃO está no papel. Quantidade diferente num item que já está não é mexida — ali a carga mudou de verdade e o caminho continua sendo o número NOVO — mas a divergência é dita no quadro (alarme calado foi o que escondeu este furo por 7 dias).
✅ O pedido que entrou também vai pro faturamento (a lista que libera a baixa), unido aos que já estavam. E o romaneio dobrado — no caso, o Nº 118, que saiu no mesmo segundo que o 119 — cai junto, com o motivo escrito: hoje os dois valem e a TANGARA está contada com 44 paletes.
⚠️ Travas: romaneio cancelado não recebe acréscimo; sem usuário identificado não acrescenta (o rastro precisa de responsável); e se o servidor não gravar, não acrescenta e não diz que acrescentou — o cancelamento do dobrado só roda depois de o acréscimo gravar, senão a carga ficaria sem papel nenhum.
🔧 Por dentro: js/24 ganhou romItensQueFaltam (casa pelo código exato, nunca por pedaço) e romAcrescentarAoRomaneio, com a gravação por /merge keyed como todo o resto; js/54 ganhou a linha linhaAcrescentos e o acrescentos entrou na reimpressão (fora dela, a 2ª via perderia a linha — a lição da composicao, v2.37.463). Papel sem acréscimo sai byte a byte igual ao de antes. Teste tests/romaneio-acrescentar-item.test.mjs (30 checagens, 11 mutações), rodando o código real contra o dado real da carga.
v2.37.1005
🔴
VIAGEM ATRASADA FICA NO APP DO MOTORISTA ATÉ SER ENTREGUE.
Dono em
08/10/2026, FBW4G22 · LUCIANO: a entrega da
ABC PRINT (viagem de 07/10, saiu 10:47) atrasou e sumiu do app quando virou o dia — o app só mostrava viagem com a data de hoje.
"se está na escala e ainda não foi entregue a entrega fica pendente, e ele consegue sair, e depois ele vai pra segunda viagem; as viagens somente somem quando ele coloca como entregue" →
"a que está atrasada fica em vermelho" →
"pode fazer". Preview aprovado:
NoNa57rV.
✅
App JP Motorista → 🚚 Entregar: viagem de até
7 dias atrás com caixa ainda não entregue continua na tela,
em cima, com o cartão
vermelho, a etiqueta
🔴 ATRASADA e a faixa
⚠️ PENDENTE de 07/10 · saiu 10:47. Ela só some quando a última parada é marcada entregue. A viagem de hoje vem logo abaixo e o "Saí da fábrica" dela continua liberado.
🔒
Não muda: a escala do sistema e o PDF da escala; o checklist do caminhão; "⚠️ Não deu — pular" não conta como entregue (a viagem continua pendente); viagem só de materiais (sem caixas) não vira pendente; cancelada some como antes.
Sem Luan.
🔧 Por dentro: js/115 JPRoteiro.faltaEntregar + JPRoteiro.viagensParaEntregar (puras); painel_motorista render da aba Entregar usa a lista nova (os avisos de carga continuam só nas de hoje). Teste tests/motorista-viagem-pendente.test.mjs (22 checagens).
v2.37.1004
📅 PADRÕES PRA TODA CAIXA SEM CADASTRO: 3.000 CX/H, 30 MIN DE AJUSTE EM CADA MÁQUINA E A PALETIZAÇÃO PADRÃO.
Dono em 08/10/2026: "o cronograma tem que ler a velocidade real das caixas … todas as caixas têm que ir com 3.000 caixas por hora e ajuste de 30 minutos cada, como padrão … os paletes têm que vir como padrão também … se a caixa já tiver velocidade ajustada não muda". Preview aprovado antes de codar.
✅ Velocidade: o cronograma, o Planejamento, a meta do Mural, o tablet e o pedido usam o cadastro da caixa naquela máquina — agora também na Die Cut e em qualquer máquina cadastrada (o campo da seção 9 da v998; sem ele, a Die Cut lê o campo do C&V ou do Slotter). Caixa sem velocidade usa o padrão 3.000 cx/h, campo novo em ⚙️ Configurações → Velocidade padrão (cx/h). O padrão da máquina (4.500 / 5.500 / 8.000) e o cx/h digitado no pedido deixaram de valer, e "⚠ sem velocidade" não existe mais.
💡 A média real virou só sugestão: ela continua na seção 9 do cadastro da caixa (apontamento + o que o sensor contou) e no modal do pedido, mas só passa a valer quando alguém clica em Usar. Antes ela entrava sozinha quando a caixa estava sem velocidade.
✅ Ajuste: o Setup padrão das Configurações (30 min) vale agora no acabamento (era 15 fixo) e em cada máquina do meio (era 0). O corte continua com o setup do cliente, quando tiver. O cartão do cronograma diz "padrão (Configurações)" quando usa o padrão.
✅ Paletes: a 📦 Paletização padrão (Config. Orçamento) vale pra toda caixa cadastrada que está sem — campo por campo: o que a caixa tem manda, o que falta vem do padrão, e o lastro sai da medida da chapa pela mesma conta da seção 8. O Plano de carga, o romaneio, o Estoque PA e o plano da caixa usam e marcam "(padrão)". Das 25 caixas sem palete no servidor, 24 passam a ter (o ACESSÓRIO da Granja Hattori não tem medida de chapa). 11 delas tinham a altura do palete vazio gravada errada (1158 a 2110 mm): acima de 300 mm vale o padrão de 150.
🔒 Não muda: caixa com velocidade ou paletização cadastrada (mesmo número de hoje); o setup por cliente no corte; o preço do orçamento (não usa essa conta). Nada é gravado nas caixas: os padrões são lidos na hora. Sem Luan.
🔧 Por dentro: js/01 jpVelocidadeDoPedido = jpVelocidadeDaCaixa → jpVelocidadePadrao, e jpSugestaoVelocidade separada; js/21 cronSetupPadrao() no acabamento e no meio; js/19 palDaCaixaComPadrao + js/08 jpPaletizacaoDaCaixa, lidos pelo js/22 plcGeoCaixa, js/03 e o plano da caixa. Teste novo tests/padroes-velocidade-setup-palete.test.mjs (31 checagens, 4 mutações); velocidade-uma-so e maquinas-fabrica-editaveis reescritos pra decisão nova (8 mutações).
v2.37.1003
📐
A REFERÊNCIA DO ARTIOSCAD NO CADASTRO DE ONDAS, E O DXF LENDO OS TIPOS DE LINHA DELE.
Dono em
07/10/2026, depois de decifrarmos o instalador do ArtiosCAD:
"pode tirar a tabela de papelão e o mapeamento de DXF" →
"pode fazer, meio-corte conta como corte". Preview aprovado:
EnQB2bY9.
✅
Comercial → ⚙️ Config. Orçamento → Compensações por onda: coluna
📐 Artios (caliper · perda interna · ganho externo da biblioteca métrica da Esko) e, ao ✏️ editar a onda, o bloco
"Referência ArtiosCAD", só leitura. E 1,5 (1/1) · B 3,0 (2/1) · C 4,0 (2/2) · BC 7,0 (4/3) · cartão 0,45. Onda sem equivalente (EB, BB, micro) mostra "—".
Nada nos seus números muda.
✅
Cadastro da caixa → Corte e Vinco → DXF → Camadas: coluna
Artios com o nome do tipo pela cor (a cor do DXF é o número do tipo de linha do ArtiosCAD) e três tipos novos no seletor:
◐ Meio-corte (cores 4 e 9),
┄ Picote de cola (7) e
📏 Vinco invertido (8). Cores 10, 11, 19 e 20 (registro, sangria, cotas, anotação) já nascem em Ignorar. Antes tudo isso caía em "corte".
✅
Pra onde o tipo novo vai: na lâmina, meio-corte soma no
corte, picote de cola no
picote, vinco invertido no
vinco (a linha de totais diz quanto de cada, já somado). No 3D, meio-corte
não dobra nem separa; vinco invertido dobra; picote de cola segue a regra do picote. No PDF/EPS pro Illustrator e no DXF da facaria, cada um sai com separação e cor próprias (
Meio-corte,
Picote de cola,
Vinco invertido; cores 4, 7, 8) — só quando a faca tem.
🔒
Não muda: DXF com cor 1/2/3 (o do Montador, o dos clientes de hoje) lê igual; o nome da camada continua mandando sobre a cor; caixa já cadastrada com DXF não muda sozinha (ao reabrir o DXF o palpite novo aparece e você confirma); orçamento, cadastro, o DXF que o sistema exporta.
Sem Luan.
🔧 Por dentro: js/23g-artios-referencia.js novo (JPArtiosRef: PAPELAO, TIPOS_DXF, refDaOnda, tipoDaCor, resumoDaOnda — dados lidos de datacenter/board.dat e Artios_DWG_DXF_-_Metric.ITUNE do instalador 24.03); js/23c cvPalpiteTipo consulta o Artios depois do nome e das cores 1/2/3, cvOpcoesTipoCamada, cvNomeArtiosDaCor, cvSomaEm, totais com meioCorte/picoteCola/vincoInvertido; js/105 entsParaFaca cor 4/7/8 e entsDeCamadas pula o meio-corte; js/106 SEP 4/7/8 + sepDe(), separações condicionais; js/108 jpOndaRefArtiosHtml; js/08 coluna na tabela. Teste tests/artios-referencia-ondas-dxf.test.mjs (11 checagens). Junto: js/23f-ard-leitor.js (leitor de .ARD, ainda sem tela; teste próprio, 9 checagens).
v2.37.1002
📋
ITEM 1.32 "CABO TRANSFERÊNCIA DE CARGA" SAIU DO CHECKLIST.
Dono em
07/10/2026, print do item:
"tirar isso da lista do checklist".
✅ O checklist do caminhão passa a ter
34 itens (era 35). Os números dos outros
não mudam (1.33 Situação dos freios continua 1.33), pra não confundir o histórico e os chamados que já citam esses números. Vale pro app do Motorista, pro papel e pra tela do sistema no mesmo ato.
🔒
Não muda: checklists já feitos com o 1.32 respondido continuam guardados como estão; chamados abertos do 1.32 na Oficina ficam até resolver.
Sem Luan.
🔧 Por dentro: js/116 ITENS_PADRAO (a config checklist_caminhao_config não existe no servidor, então a lista é a do código). Se um dia quiser tirar/pôr item sem versão nova: Expedição → Checklists → ⚙️ Itens do checklist.
v2.37.1001
📋
CHECKLIST ABRE NUM POP-UP NO MEIO DA TELA — VISUALIZAÇÃO RÁPIDA.
Dono em
07/10/2026, depois de ver os cartões (v999):
"quero que abra no meio da tela o checklist como pop-up, e com o Esc ou botão sai — como se fosse uma visualização rápida".
✅
Expedição → 📋 Checklists do caminhão: clicou no cartão (ou em 📋 Abrir) e o checklist abre por cima, no meio, com o fundo escurecido: cabeçalho com caminhão, data e hora, motorista e situação; dentro, as ocorrências com o "Dar baixa (PCP)" e o checklist como sai no papel; embaixo, 🖨️ Imprimir e Fechar. Fecha com
✕,
Fechar ou
Esc. A lista fica atrás, no mesmo lugar, sem rolar. Clicar fora não fecha (regra da casa, v825).
🔒
Não muda: o conteúdo do detalhe (ocorrências, baixa, papel), a busca, os cartões, Imprimir.
Sem Luan.
🔧 Por dentro: js/117 modalCkc() cria #modal-ckc.modal-bg filho do <body> (o Esc global do js/01 fecha o .modal-bg.show de cima); renderDetalhe desenha dentro dele; ckcAbrir sempre abre, ckcFechar limpa; o #ckc-detalhe embaixo da lista saiu. Teste tests/checklists-em-cartoes.test.mjs. Visualização conferida no navegador com o papel real.
v2.37.1000
🩹
19 ARQUIVOS JS CARREGAVAM SEM CACHE-BUST — A TELA NOVA NÃO CHEGAVA ("AINDA NÃO").
Dono em
07/10/2026, com o sistema em v999 e a aba Checklists ainda com a tabela velha:
"ainda não… já atualizei".
🔎
Causa: o servidor entrega todo
.js com
cache-control: max-age=3600, public. Quem tem
?v=hash na URL muda de endereço a cada mudança e o navegador busca o novo; mas
19 scripts entraram sem o ?v= (js/104, 105, 107, 108, 112, 113, 114, 115, 116, 117, 119, 122 — no sistema e nos apps da Escala, Motorista, Oficina, Manutenção, Compras, Operador, Almoxarifado JPE). Esses o navegador guardava por até 1 h (e o Safari mais), então o js/117 novo (cartões, v999), o js/116 (checklist pendente, v967) e o js/122 (PDF da escala) só chegavam quando o cache vencia — por isso "atualizei e ainda não".
✅ Todos os 19 ganharam
?v= e o bump carimba o hash do conteúdo neles, igual aos outros: mudou o arquivo, muda o endereço, chega na hora. Quem já abriu o sistema hoje precisa de
um F5 depois desta versão (o sistema.html em si não é guardado).
🔒
Não muda: nenhum comportamento — só o endereço dos scripts.
Sem Luan.
🔧 Por dentro: <script src="js/NNN-x.js"> → ?v=0 e o scripts/cache-bust.sh (que só mexe em quem tem ?v=) passou a cobrir eles. Lição pro CLAUDE.md: script novo entra sempre com ?v=0; o bump troca pelo hash.
v2.37.999
📋
CHECKLISTS DO CAMINHÃO EM CARTÕES, POR DIA, COM BUSCA.
Dono em
07/10/2026, print da tabela:
"vamos deixar mais organizado: coloca tudo em um card e por dia; um campo de pesquisa por caminhão, motorista e por dia".
✅
Expedição → 📋 Checklists do caminhão: a tabela corrida virou
cartões agrupados por dia (do mais novo pro mais velho), cabeçalho do dia com "7 checklists · 5 com problema · 24 ✗". Cada cartão: caminhão com apelido, situação colorida (verde ok · laranja problema · azul oficina atendendo · vermelho parado · amarelo em andamento), motorista e hora, km e ✓/✗
separados (o "958.50035 ✓" grudado some), ocorrências em etiquetas, 📋 Abrir / 🖨️ Imprimir.
✅
🔎 Busca que filtra enquanto digita: placa, apelido (DAF V) ou motorista, sem acento.
📅 um dia ou chips
Hoje · Ontem e hoje · 7 dias · 30 dias · tudo (entra em 7 dias) e "só com problema".
🔒
Não muda: KPIs, faixa dos caminhões parados, Atualizar, Exportar CSV (segue o mesmo filtro), ⚙️ Itens, o detalhe ao abrir e a baixa do PCP. Nenhum dado.
Sem Luan.
🔧 Por dentro: js/117 — F = { q, dia, periodo, soProblema }, faixa() (dia/período → de/até do JPCheck.filtrar), bateBusca (sem acento, placa normalizada), docsFiltrados, cartão + grupos por dia no render(), ckcBusca com atraso de 120 ms mantendo o cursor. Teste tests/checklists-em-cartoes.test.mjs. Preview aprovado: https://claude.ai/artifact/Em31KtsJSgxpbYrK7WmcLX
v2.37.998
🏭 VELOCIDADES SÓ DAS MÁQUINAS DO ROTEIRO — A SEÇÃO 9 DO CADASTRO DA CAIXA OBEDECE À SEÇÃO 7.
Dono em 07/10/2026, com o cadastro aberto: "nesse campo só quero as máquinas que tiver cadastrada no circuito … se acrescentar mais uma máquina ela tem que aparecer aí também". Preview aprovado antes de codar.
🔎 Como era: a seção 9 · Velocidades por máquina mostrava SEMPRE as 4 de fábrica. Uma caixa Slotter → Coladeira ficava com Corte e Vinco e Grampeadeira em branco dizendo "sem produção medida", e a máquina do meio (acopladeira, verniz…) que estava no roteiro nunca aparecia.
✅ Agora quem manda é o 🏭 Roteiro de produção da seção 7 (1ª máquina → processos do meio → fechamento): só essas máquinas aparecem, na ordem do roteiro. Trocou a 1ª máquina, o fechamento ou pôs/tirou um processo do meio, a seção 9 acompanha na hora.
✅ Máquina acrescentada ao roteiro ganha campo próprio: processo do meio (🔁) ou 1ª máquina cadastrada (offset, die cut…) entram com o nome e o ícone do cadastro de máquinas e com a sugestão pelo histórico (💡 + Usar) igual às de fábrica. A velocidade fica gravada na caixa (velMaquinas[chave]).
✅ Roteiro incompleto (sem 1ª máquina ou sem fechamento) → as 4 máquinas como sempre, com o aviso "defina o roteiro na seção 7".
🔒 Nada é apagado: máquina que saiu do roteiro some da tela mas a velocidade dela continua na caixa (a linha de aviso diz quantas estão escondidas e qual tinha velocidade); volta a aparecer se a máquina voltar. Preço, cronograma, pedido e o tablet do operador não mudam — ninguém lê nada novo nesta versão; o campo das 4 de fábrica é o mesmo de antes (velSlotter, velCorte, velColadeira, velGrampeadeira).
🔧 Por dentro (js/08): a grade virou uma só (#cx-vel-grid, cada máquina de fábrica no seu data-vel-maq), cxVelMaquinasDoRoteiro() decide a lista pura e cxVelRender() desenha — chamado pelo cxRotRender(). O histórico de produção passou a casar máquina cadastrada pelo nome exato (nunca por pedaço) em outras[chave], com teto pela velocidade da caixa nela ou pelo velPadrao. Histórico de alterações da caixa compara o novo campo. Teste tests/velocidades-do-roteiro.test.mjs (48 checagens). Sem Luan.
v2.37.997
📄
PDF DA ESCALA: O NOME DO MOTORISTA EM DESTAQUE.
Dono em
07/10/2026, depois de testar o Exportar PDF no app e no sistema ("veio certinho"):
"destaca o nome do motorista".
✅ Em cada viagem do papel, a linha do motorista virou uma
faixa azul-clara com barra à esquerda, nome maior (17 px) e a placa à direita — bate o olho e acha o motorista. Só isso.
🔒
Não muda: o resto do papel, o texto do grupo, nada de dados.
Sem Luan.
🔧 Por dentro: js/122 css(), regra .ep-h / .ep-h b.
v2.37.996
📄 O NÚMERO DO ROMANEIO NA TABELA DO HISTÓRICO DE CARGAS.
Dono em 07/10/2026, olhando a tabela: "coloca o número do romaneio visual para ficar fácil de achar". Preview aprovado antes de codar.
✅ Coluna nova "ROMANEIO" (Expedição → 📜 Histórico Cargas), entre CLIENTE e PLACA: um chip 📄 Nº 135 por romaneio valendo da carga. Até aqui o número só aparecia três cliques depois (👁 → chip do cliente → "esta carga já tem romaneio Nº …").
✅ Clique no número abre a 2ª via na hora — o mesmo papel, mesmo número, mesma data. Não emite nada.
✅ O 🔎 da tela acha pelo número: digitou 119 ou nº 119, aparece a carga de 29/09 (cliente, motorista, placa e nº do pedido continuam valendo).
✅ Carga com 2+ clientes: um chip por cliente, com o nome pequeno. O mesmo cliente com 2 papéis valendo (o erro de 29/09: 118 + 119 da TANGARA) ganha borda amarela e ⚠ — a tabela passa a acusar o dobro em vez de esconder. Carga concluída sem papel valendo fica amarela: "⚠ sem romaneio valendo" — é a carga que alguém corrigiu e esqueceu de emitir o novo.
🔒 Cancelado não aparece na coluna (continua no 📄 Romaneios emitidos, riscado). Nenhum número é emitido, cancelado ou renumerado por esta tela. Os 4 cartões de cima, o 👁, o ✏️ e o app da Expedição não mudam.
🔧 Por dentro: js/10 histRomaneiosDaCarga (lista do js/24 filtrada por origemId, "mesmo cliente" pela chaveDoRomaneio do js/54 — a mesma régua da emissão e do cartão) + histCelulaRomaneio; histCargaBate aceita o nº do romaneio (valendo ou cancelado); clique chama reimprimirRomaneio dentro do clique (é como o window.open abre). Teste tests/romaneio-no-historico-de-cargas.test.mjs (23 checagens, dado real da carga de 29/09).
v2.37.995
📄 ROMANEIO DA CARGA CORRIGIDA: 4 CONSERTOS — A CX 15 QUE ESTAVA NA CARGA E NÃO NO PAPEL.
Dono em 06/10/2026: "nesse romaneio está falando que tem a caixa 15 mas não está no pdf… eu corrigi esse romaneio e adicionei manualmente" · "quero histórico de correção também". Preview aprovado antes de codar.
🔎 O que aconteceu (medido no servidor, carga do LUIS CARLOS GUETTI · CPN8C54 · 29/09): o Nº 117 saiu com a CX 15 às 09:37; às 09:54 os 7 paletes foram tirados pelo ✏️ (certo: o 117 foi cancelado); às 10:03 dois cliques no 📄 TANGARA tiraram DOIS números (118 e 119), os dois sem a CX 15 e os dois valendo; às 13:04 e em 30/09 01:09 os paletes voltaram pelo ✏️ e nada cancelou o 118/119 — a aba estava com a lista velha de romaneios e o aviso ficou calado. O PDF do 119 é a foto das 10:03.
✅ 1. Um clique, um número. O chip 📄 fica "⏳ TANGARA — emitindo…" até o papel abrir; o segundo clique avisa "Já estou emitindo o romaneio da TANGARA" e não emite. Outro cliente da mesma carga não fica preso.
✅ 2. Pôr ou tirar palete pelo ✏️ relê os romaneios do servidor antes de cancelar e diz quais caíram: "romaneios Nº 118 e Nº 119 cancelados — emita o novo pelo 📄 TANGARA". Não achou nenhum: aviso vermelho "NÃO achei romaneio da TANGARA desta carga pra cancelar — confira em 📄 Romaneios emitidos". O palete entra ou sai do mesmo jeito; o aviso não barra.
✅ 3. O número do pedido no papel e no cartão da carga vem do PEDIDO quando o palete tem vínculo (o número do palete é cópia da bipagem): a CX 15 sai como 24190, não "24184, 24190" — o 24184 é o CX 02 FLOPS 24X500. Palete sem vínculo, ou com número posto na mão, continua como está.
✅ 4. 🛠️ Correções desta carga (14) no cartão da carga (👁 no Histórico de Cargas), recolhido com a contagem, em ordem do tempo, com palete, caixas, motivo e quem fez. Dentro do ✏️ a lista inteira — não mais só as últimas 5.
🔒 Nenhum papel já emitido é apagado ou renumerado (116, 117, 118, 119 ficam no histórico). O desenho do romaneio, o app da Expedição, o estoque PA e o livro de saídas não mudam. Os paletes da carga de 29/09 não foram reescritos.
▶ O que falta é seu: Expedição → 📜 Histórico Cargas → 👁 na carga de 29/09 → 📄 TANGARA → "Emitir NOVO e cancelar os anteriores (Nº 118, Nº 119)". O novo sai com os 29 paletes, CX 15 inclusa, Ped 24190.
🔧 Por dentro: js/24 trava por carga|cliente (try/finally) e marca o chip; js/79 cancelarRomaneiosDoCliente devolve {n, numeros, lidoDoServidor} e o histórico virou historicoHtml (um desenhador só, pro cartão e pro ✏️; o palete vem do paletNum gravado a partir de hoje ou do _pN do id no rastro antigo); js/54 numPedDePalete segue o pedido vivo (respeita numPedManual) e pedidosDaCarga idem; js/10 chips com data-rom-chip e o histórico embaixo deles. Teste tests/romaneio-carga-corrigida.test.mjs (34 checagens com o dado real em tests/fixtures/carga-cpn8c54-2026-09-29.json; contra a main de antes, 28 falham).
v2.37.994
🔎 ZOOM NO ARRUMADOR — PRA CHEGAR PERTO DA ARTE.
Dono em 05/10/2026, com a DEUSA aberta: "está muito pequeno, quero dar zoom para mudar e arrumar a arte — está muito longe". Preview aprovado antes de codar.
✅ O painel ficou largo (era 640 px, virou até 1.180) e ganhou zoom: roda do mouse, dois dedos no tablet, os botões − / + / ⤢ encaixar, e as teclas + − 0. O zoom guarda o ponto do papel que está embaixo do ponteiro, então dá pra mirar no código de barras e chegar nele.
✅ Arrastar em cima da arte ou de uma peça move ela (e já escolhe ela); arrastar no vazio corre a tela, sem mexer em nada — como no Illustrator e no Google Maps.
📏 Por que estava pequeno: a faca dele é 1.528 × 488 mm, quase três vezes mais larga que alta, e o desenho encolhia até caber na largura de 640 px. Medido antes e depois na mesma tela: a faca saía com 320 px e agora sai com 772 — e o zoom vai até 24×.
🐛 E apareceu um defeito que ninguém tinha visto: o arrasto morria no primeiro passo. Os ouvintes do dedo moravam no próprio desenho, que é refeito a cada milímetro — ou seja, o gesto perdia o dedo no caminho. Medido: um arrasto de 80 px andava 47,7 mm quando devia andar 363,5. Agora anda inteiro.
🔒 O zoom é só a lente: não muda medida, não entra no que é salvo e não vai pra imagem baixada — o ⬇ Baixar continua saindo inteiro, no tamanho de verdade. E a vista é presa: por mais que se arraste, a faca não some da tela.
🔧 Por dentro: a razão do viewBox passou a casar com a do painel (sem isso a conta de px→mm erra e o zoom no ponto do dedo não fecha), o flip de y deixou de depender da vista, as linhas da faca ficaram pointer-events:none (uma linha fina roubava o clique) e mantêm a mesma grossura na tela em qualquer zoom. Ouvintes no contêiner, pointermove sempre passive e a roda só no palco — a regra que já salvou a rolagem do Mac (v2.37.373). Teste tests/arrumar-arte-zoom.test.mjs no Chrome de verdade (31 checagens, 10 mutações).
v2.37.993
✂️
CAIXA DE CORTE E VINCO NÃO TEM VINCO DE SLOTTER — O RISCADOR DE OUTRA CAIXA VAZAVA PELA JANELA DO CADASTRO.
Dono em
07/10/2026:
"a PARMEGIANE G da DCX está como corte e vinco, no operador está como slotter". O cadastro estava certo; a ficha do app do operador mostrava "Impressora 30 × 222 × 332 × 222 × 332 × 15" e "Riscador 223 × 232 × 223" — esse riscador era o da
FARMASI 04 (maleta).
🔎
A causa: a janela "Editar Caixa" é uma só e a linha do riscador só é escrita em caixa de dobra; no corte e vinco o cálculo saía antes sem apagar, e o salvar gravava o texto que ficou na tela (ou o valor velho).
44 das 49 caixas de corte e vinco estavam com riscador de slotter gravado — e a Onduladeira mostrava "Vincos (riscador)" numa chapa lisa.
✅
App do operador → Ficha técnica: corte e vinco mostra
✂️ Chapa do corte e vinco (C × L do cadastro, lisa), poses por chapa e a faca; as linhas Impressora/Riscador só aparecem em caixa de dobra.
✅
Cadastro → Editar Caixa: corte e vinco grava riscador
vazio; a linha da tela é zerada a cada abertura; o bloco "4 · Compensações" não aparece mais no corte e vinco (o modo folha o mostrava de novo).
✅
Onduladeira e PCP → Programar: corte e vinco é tratado como
chapa lisa ("📄 Chapa lisa — corte e vinco · sem vinco de riscador"), igual chapa e folha do facão.
🧹
Limpeza das 44 caixas: node scripts/limpar-riscador-cv.mjs --sim (ensaio) e sem
--sim pra gravar — cópia do antes em
backups/, com
--desfazer.
🔒
Não muda: modelo das caixas, chapa, poses, faca, clichê, arte; caixa de maleta/dobra continua igual em todas as telas.
Sem Luan.
🔧 Por dentro: painel_operador.html calcMedidasFicha devolve {cv, chapa, poses, faca} + blocos #prod-medidas-cv/#prod-medidas-dobra; js/08 cxZerarLinhasVinco() (abertura + ramo CV), salvar riscador:'' em CV, cxModoFolha respeita CV; painel_onduladeira ondCaixaEhCV + ondVincos → null; js/15 progCaixaEhCV. Teste tests/corte-vinco-sem-riscador.test.mjs (23 checagens).
v2.37.991
📄
A ESCALA DO DIA EM PDF — A MENSAGEM DO GRUPO NUM PAPEL, UM ARQUIVO SÓ.
Dono em
06/10/2026:
"sabe aquela mensagem que manda no grupo da escala? podemos fazer em um PDF" ·
"quero que seja a opção Exportar em PDF, porém tem que ser 1 PDF somente" ·
"posso clicar na engrenagem e abrir a categoria pra cadastrar".
✅
App JP Escala → 📢 Postar escala: botões
📄 Exportar PDF e
🖨️ Imprimir ao lado de Copiar / WhatsApp. O PDF é gerado quando a prévia abre e fica pronto: no celular o botão abre o compartilhar com
só o arquivo (vai direto no grupo); no PC baixa
escala-2026-10-07.pdf.
Um PDF com o dia inteiro (as 15 viagens de quarta 07/10 em 2 folhas A4, viagem nunca cortada no meio).
✅
Sistema → Expedição → Escala:
📄 Exportar PDF e 🖨️ na barra, o mesmo papel.
✅
O papel: logo da JP, "🚛 ESCALA DE ENTREGAS - JP · Quarta-feira, 07/10/2026 · 15 viagens · postada 06/10 18:45", uma caixa por viagem (nº, motorista, caminhão com apelido, roteiro 🏭 sai → paradas com endereço + 🧭 mapa + 🔽/🔼/🛒 → 🏭 volta, saída, retorno SIM/NÃO, status, 💬 obs), faixa 🔁 "escala alterada" quando for o caso, rodapé "Boa viagem a todos" + gerado quando/por quem. Gerar o PDF carimba "postada" igual copiar/WhatsApp.
✅ A dica "📂 categorias de ⚙️ Materiais" ao lado do 🔽/🔼 virou botão: clica e abre o cadastro das categorias (sistema e app).
🔒
Não muda: o texto do grupo continua igual; nada na escala, nos motoristas ou nos dados.
Sem Luan.
🔧 Por dentro: js/122-escala-papel.js (JPEscalaPapel.corpo/html/css(raiz)/nomeArquivo, puro, lê o JPRoteiro; status, mapa e logo vêm de quem chama — §9.13, um documento só); app escalaPrepararPdf/escalaPdfBlob/ESC_PDF (html2pdf → blob → navigator.share({files}) ou download); sistema escExportarPdf/escImprimirEscala (js/08). html2pdf (cdnjs 0.10.1, o mesmo do romaneio) entrou nas duas telas. Teste tests/escala-pdf.test.mjs. Preview aprovado: https://claude.ai/artifact/X9F8o3XC2PJ1B1aeLAxhka
v2.37.990
⬇ BAIXAR A COMPOSIÇÃO — PRA MANDAR PRO CLIENTE.
Dono em 05/10/2026: "faz o baixar a composição". Preview aprovado antes de codar.
✅ Na barra do 🎨 Arrumar na faca, ao lado do Salvar, entrou o ⬇ Baixar…. Ele pergunta o quê, porque são duas coisas diferentes: 🧊 a caixa montada (fechada, de canto, com a arte e as peças — é o que o cliente entende, a mesma foto que já sai no Plano) ou 📐 a composição plana (a chapa aberta com tudo no lugar e as linhas da faca por cima — é o que o designer entende).
✅ Sai um PNG com o nome da caixa e a data. Conferido: a plana saiu em 2.600 × 1.813 px com a arte, as duas peças e a faca; a montada, 1.400 × 980 px com a caixa fechada.
⚠️ Não serve pra clicheria — e o nome do arquivo diz isso ("… - nao serve pra clicheria - 05-10-2026.png"). É imagem ponto a ponto; impressão pede vetor. O arquivo da clicheria continua sendo o PDF do designer.
🔒 Baixar não grava nada: não salva a caixa, não sobe pro servidor, não muda número nenhum. Sai o que está na tela agora — e por isso a escolha avisa quando há ajuste não salvo. Deu erro no meio, ele não baixa e diz: um PNG em branco na mão do cliente é pior que um "não consegui".
🔧 Por dentro: js/121 ganhou o botão, a escolha e as duas montagens — a caixa usa o mesmo JPCaixa3D.foto do Plano (não uma segunda conta) e a plana desenha a composição + as linhas da faca num canvas. O js/120 recusava fotografar com a tela do 3D aberta — herança do 3D antigo, onde a foto reusava aquela tela; hoje ela monta a própria, então quem sabe disso pode pedir por comATelaAberta. Sem esse sinal nada muda pra ninguém. Teste tests/baixar-a-composicao.test.mjs (26 checagens, 4 mutações).
v2.37.989
🎨 AS PEÇAS DA ARTE: A LOGO, O CÓDIGO DE BARRAS, CADA UMA NO SEU LUGAR.
Dono em 05/10/2026: "tem como fazer um editor de vetor?" · "eu clico e arrasto para onde eu quiser, a arte" — e, escolhendo entre três caminhos, o 3: mandar as peças separadas e colocar cada uma. Preview aprovado antes de codar.
✅ Na mesma tela do 🎨 Arrumar na faca (Cadastros → Caixas → 6.5 Arte) entrou uma lista de peças do lado. 📎 Juntar peças aceita uma ou várias de uma vez (PNG, JPG ou PDF). Clica na peça — na faca ou na lista — e arrasta: só a escolhida se mexe, as outras ficam paradas. As setas, o − menor / maior + e o ↺ automático passam a valer pra ela.
✅ A lista é a ordem: quem está em cima aparece na frente, e dá pra trocar com ▲ ▼. A arte do designer é o fundo e fica marcada como tal, pra não sair do lugar sem querer. O 🗑 tira a peça da caixa (e avisa que o arquivo não é apagado).
✅ O 3D acompanha com tudo junto — a arte e as peças.
⚠️ Isto é pra VER: o 3D, o mockup do Plano, a arte no palete e na carga. O arquivo que vai pra clicheria continua sendo o PDF que o designer mandou — ele não é tocado. Montar aqui e mandar pra impressão perderia qualidade (a composição é ponto a ponto, e impressão pede vetor). Está dito no preview e aprovado assim.
🔒 Não muda nada: nenhum número; caixa sem peças fica exatamente como está hoje; e quem só quer mexer na arte inteira usa o 🎨 igual a ontem.
🔧 Por dentro, e é a decisão que fez isto caber em dias em vez de semanas: os cinco desenhos do sistema sabem mostrar uma imagem com um encaixe. Em vez de ensinar os cinco a empilhar peças, o jpArteComposta (js/101) junta tudo numa imagem só, do tamanho da faca, e o encaixe dela é 1 pra 1 — nenhum dos cinco mudou uma linha (conferido no teste: js/70, js/19, js/120 e js/22 não sabem o que é uma peça). Peça que não carrega é pulada, nunca derruba a composição; o canvas tem teto de 8192 px (acima disso o navegador devolve a tela em BRANCO, sem erro — §9.10). Vestir o 3D tem folga de tempo, senão travaria no arrasto. As peças ficam em arteCamadas na caixa, com o campo nos dois literais do salvar (§9.14). Teste tests/pecas-da-arte.test.mjs (38 checagens, 5 mutações).
v2.37.988
🧊 OS BOTÕES DE VISTA NO 3D DA CAIXA: Iso · Topo · Frente.
Dono em 05/10/2026: "quero igual às 3 imagens do Montador de Corte e Vinco" → "os botões de vista no 3D da caixa". Preview aprovado antes de codar.
✅ Na barra de baixo do 🧊 Ver e ajustar em 3D, ao lado do "parar de girar", entraram 🧊 Iso (a caixa de canto, a vista de sempre), ⬇ Topo (de cima, pra conferir as abas de fechamento) e ▭ Frente (reta, pra olhar a arte no painel). Vale nos cinco lugares que abrem esse 3D.
✅ São os MESMOS ângulos do Montador — e por construção: a lista mora num lugar só (js/118, motor3D.VISTAS) e os dois leem dela. Dois conjuntos divergiriam na primeira vez que alguém achasse que "o topo está meio torto".
⚠️ Clicar numa vista PARA o giro. A caixa gira sozinha ao abrir; sem parar, o Topo e o Frente sairiam do lugar no quadro seguinte e pareceria que o botão não funcionou. É o mesmo que já acontece ao clicar num painel pra ajustar a dobra — e o ▶ girar continua ali pra voltar.
🔒 Não muda nada: nenhum número, e nada sai da barra — Desmontar, a barrinha, girar, papel, base e salvar ficam onde estavam. "Aberta" e "Fechada" já existiam: são as duas pontas da barrinha.
🔧 Por dentro: js/118 ganhou VISTAS (exportada em motor3D) e os botões dele passaram a ler de lá em vez do número escrito à mão; js/120 monta os botões pela lista e liga cada um no M.view() que o motor já tinha. Sem o js/118 na página os botões não nascem e o resto da barra segue igual. Teste tests/botoes-de-vista.test.mjs (19 checagens, 3 mutações).
v2.37.987
🎨 ARRUMAR A ARTE NA FACA — a tela 2D, com o 3D acompanhando ao vivo.
Dono em 05/10/2026: "quero que monta um editor de imagens igual o Illustrator para editar e arrumar as imagens dentro da faca eps ou dxf; pode ser dentro do 3D mesmo — quando for arrumar a imagem em 2D já atualiza em 3D". Preview aprovado antes de codar.
🔎 O que faltava: onde a arte caía na faca era 100% calculado. Errou a conta, não existia como corrigir na mão — e o 3D, o Plano e o palete saíam todos com a marca no lugar errado.
✅ A tela: Cadastros → Caixas → abrir a caixa → 6.5 Arte → 🎨 Arrumar na faca. A faca aparece plana (corte em vermelho, vinco tracejado) com a arte por baixo. Arraste pra mover, as setas (ou as do teclado) andam 1 mm, os botões − menor / maior + esticam de 1% em 1%, e o ↺ automático devolve a posição que o sistema calcula. O rodapé mostra o quanto andou, em mm, e acende "não salvo" enquanto você não gravar.
✅ O 3D acompanha ao vivo: com a caixa aberta em 3D atrás, cada toque já veste a caixa — você vê a marca caindo no painel certo enquanto mexe.
✅ Salvou, vale nos CINCO desenhos: 3D da caixa, mockup do Plano, arte no palete, arte na carga e o layout do Plano. Não foi preciso mexer em nenhum deles — todos chamam a mesma conta de encaixe, e é no fim dela que o ajuste é aplicado.
🔒 Não muda nada: nenhuma medida, peso, preço, paletização ou pose; o PDF da arte não é tocado (o ajuste é uma anotação na caixa); e caixa sem ajuste salvo fica exatamente como está hoje. Sair sem salvar devolve o 3D ao que está gravado.
⚠️ Fase 1 — ainda não gira e ainda é uma arte por caixa, e está dito no preview: a conta que os cinco desenhos leem não tem ângulo nem segunda imagem. Girar obriga a mexer nos cinco; layers são um modelo novo. A textura do papel é de outra frente (cadastro do papel → 🧊 Textura no 3D).
🔧 Por dentro: js/121-arrumar-arte.js novo (JPArrumarArte.abrir(cx, {aoSalvar}) — a tela não alcança CAIXAS, STATE nem a API: quem abre entrega a caixa e recebe o ajuste); js/101 ganhou ajustar() no fim do arteCalibracao3D (escala em volta do CENTRO, pelo canto a arte fugiria a cada toque; dx/dy em mm da faca) e o ajuste viaja dentro da arte (jpArteDaCaixa), que é o que o faz chegar nos cinco sem tocar nos pontos de chamada; js/08 o botão, o salvar (arteAjuste na caixa, apagado no "automático") e o campo nos dois literais do salvar — fora deles ele morreria na primeira edição (§9.14). Teste tests/arrumar-arte-na-faca.test.mjs (42 checagens, 6 mutações, com a faca e a arte reais do acervo).
v2.37.986
🧊
O VÃO NO MEIO DA CAIXA FECHOU: AS ABAS SE ENCONTRAM NO CENTRO E AS LATERAIS FICAM NA BORDA DO FUNDO.
Dono em
05/10/2026, testando a 984 no ar:
"tem um vão no meio da caixa, isso deve ser compensação".
🔎
A causa: não era a compensação da chapa — era o motor. A dobra arredondada "comia" um pedaço do comprimento do painel e a parte reta nascia um raio além do vinco: cada aba comprida (raio maior, por ficar por fora) perdia uns 3 mm, as laterais abriam 2 mm pra cada lado, e no meio da tampa sobrava um vão.
✅ Agora a parte reta de cada painel começa
na linha do vinco: o alcance do painel dobrado é exatamente o comprimento dele na chapa. As abas se encontram no centro, as laterais ficam na borda do fundo, e a caixa fecha. O arco continua com o mesmo raio.
🔒
Não muda: nenhum número; andares, textura e arte da 981–984.
Sem Luan.
🔧 Por dentro: js/118 build — Lb = min(rInP, depth·0,45) no lugar de rInP·φ. Teste em montador-motor3d-fabrica.
v2.37.985
🖨️ O RECADO COBRA A FACA, E O CADASTRO AVISA QUANDO ELA VOLTOU DENTRO DA ARTE.
Você exportou a faca, desenhou a arte por cima no Illustrator e devolveu o arquivo — com a faca junto. Se esse arquivo for pra clicheria, as linhas de corte, vinco e cota saem impressas na caixa. Preview aprovado antes de codar ("faz as duas").
✅ O recado dentro do arquivo mudou. Ele dizia "nao mexa na faca" — e era exatamente isso que fazia ela ir junto. Agora manda apagar, e diz como: no EPS, Selecionar ▸ Mesma ▸ Cor do traço nas cores Corte, Vinco e Cotas (lá não existe camada: o que separa as linhas é a cor); no PDF, apagar as camadas FACA e COTAS, um clique em cada. Os dois terminam com "se ficarem, saem impressas na caixa". Saiu também o "selecione o grupo", que não existe mais.
✅ E o cadastro confere a arte que volta. Em Cadastros → Caixas → abrir a caixa → 6.5 Arte, na mesma barra do "arte encaixada", aparece 🖨️ a faca ficou dentro da arte — Corte, Vinco e Cotas ainda estão desenhados, e o mouse em cima diz como tirar. Conferido no seu arquivo de verdade: acusa as três.
🔒 Avisa, nunca barra: você salva, produz e manda do mesmo jeito — o aviso só não deixa passar calado. Arte limpa não diz nada, e arquivo que não é PDF ou que não deu pra ler também não (não acusa no escuro). Swatch sobrando no painel não acende o aviso: a conferência não para em "a cor existe", ela confere se a cor está pintando alguma coisa.
🔧 Por dentro: js/106-faca-eps.js — o recado do EPS e o do PDF, e jpFacaCores(), que diz os nomes das cores da faca (uma lista só: cor nova aqui é enxergada pela conferência sem ninguém lembrar de atualizar uma segunda lista). js/101-arte-na-faca.js — arteFacaDentro(buf) lê o PDF/AI, acha a separação declarada, o apelido do recurso que aponta pra ela e se esse apelido pinta no desenho; a barra só mostra. ⚠️ Stream sem compressão também é lido — descartá-lo fazia a conferência dizer "limpa" num arquivo sujo. Teste tests/aviso-faca-na-arte.test.mjs (24 checagens, 4 mutações, contra o arquivo real do dono e duas artes limpas); o faca-em-eps trocou de lado na afirmação do recado, de propósito.
v2.37.984
🧊
A ARTE NO 3D SEM BORDA BRANCA E SEM SERRILHADO.
Dono em
05/10/2026, testando a 983 no ar:
"o desenho está com as bordas brancas e serrilhada".
🔎
A causa: no PDF o contorno das letras é tinta misturada com branco (suavização); a 983 só deixava transparente o branco puro, e a franja clara ficava opaca em cima do kraft.
✅ Agora a tinta é
descolada do fundo branco pixel a pixel: quanto mais claro o pixel, mais transparente ele fica, e a cor volta a ser a da tinta. Letra vermelha continua vermelha; a borda dela se funde com o papel, sem halo e sem serrilhado.
🔒
Não muda: nenhum número; textura, papel automático e tudo da 983.
Sem Luan.
🔧 Por dentro: js/118 arteSemBranco — alpha = 1 − canal mais claro/255, cor = 255 − (255 − c)/alpha (un-blend sobre branco). Teste em papel-textura-3d.
v2.37.983
🧊
A FOTO DO PAPEL SAI UNIFORME E CLARA, A ARTE COM AS CORES DELA; NO PLANO, A FACE DO PACOTE COMEÇA DEPOIS DA ABA DE COLA E A CAMADA DA FACA NÃO RISCA MAIS A ARTE.
Dono em
05/10/2026:
"coloquei a textura, mas ficou com bordas — quero uniforme, e parece com multiply do Illustrator" ·
"clara, com cara de kraft, não amarelada" ·
"no pacote ainda aparece a linha dos vincos e a do lap, e está empurrando a lateral pra fora".
✅
Textura sem emenda: a foto do papel repete
espelhada (as bordas casam com elas mesmas) e, ao enviar, o tom é
nivelado (tira o degradê da foto, fica só a fibra) — some o xadrez de azulejos.
✅
Cor de verdade: a foto e a arte deixaram de ser marcadas como sRGB (com a saída linear isso escurecia e saturava: o kraft claro virava laranja). A arte entra
com as cores dela, sem multiplicação; o branco da arte vira transparente e mostra o papel. A caixa com arte remonta quando a imagem termina de carregar (antes podia ficar com o fundo branco cru).
✅
Pacote fechado / palete: a face desenhada começa
depois da aba de cola (ela fica dobrada pra dentro), então a lateral não é mais empurrada.
✅
Arte sem a faca: ao rasterizar o PDF da arte, as camadas chamadas faca / dieline / corte / vinco ficam
invisíveis na imagem (continuam no arquivo: é delas que sai a medida). Sem camada nomeada, nada muda.
🔒
Não muda: nenhum número; o cadastro da textura é o mesmo (quem já enviou foto pode reenviar pra ganhar o nivelamento).
Sem Luan.
🔧 Por dentro: js/118 MirroredRepeatWrapping, azulejo espelhado 2×2 e arteSemBranco em arteNoPapel, sem sRGBEncoding; js/120 vestir remonta ao carregar; js/08 _nivelarTexturaPapel (divide pelo borrão, remultiplica pela média); js/19 palArteRegiao começa em x0 + aba; js/101 rasterizar com optionalContentConfig (pdf.js 3.11). Testes: papel-textura-3d (30), palete-arte-gira-e-encaixa (17).
v2.37.982
🧊 NO 3D, A ABA DE COLA ENTRA POR DENTRO DA CAIXA — E NÃO APARECE MAIS POR FORA.
Dono em 05/10/2026: "a caixa está sem o 3d, o lap está por fora da caixa" · "o lap fica do lado de dentro da caixa, não do lado de fora, somente do lado de dentro". Preview aprovado antes de codar.
🔎 A causa: o 3D dobrava na linha exata do vinco, sem folga nenhuma pra espessura do papelão. Dando a volta no tubo (quatro dobras de 90°), a aba de cola voltava na mesma fatia do painel em que ela cola — as duas chapas no mesmo espaço, e a aba aparecendo por cima. Medido no 3D de verdade, com a faca da caixa 06 da MITTO e onda de 3 mm: a face em 0,0 → 3,0 mm e a aba em 0,0 → 3,0 mm, idênticas.
✅ Agora a aba entra uma espessura por dentro e fica encostada embaixo da chapa, como no papelão de verdade. Vale pra todas as abas que estavam uma dentro da outra, não só a de cola (decisão do dono: "pode fazer todas"): na MITTO 06 são 4, na PARMEGIANE P são 4, na BANDEJA F0427 nenhuma — caixa sem o problema não muda em nada.
✅ Ela entra conforme a caixa fecha: com a chapa aberta (◀ Desmontar no fim) a aba fica no plano do papel, como é de verdade, e vai se enfiando embaixo da outra chapa enquanto a caixa monta.
🔒 Não muda nada fora do 3D: nenhuma medida (C × L × A, chapa, refile), nenhum peso, preço, paletização, poses, faca, EPS, PDF ou DXF. Nenhum ângulo de dobra e nenhuma marcação sua de "dobra / não dobra". Conferido painel a painel nas 3 facas reais do cadastro: árvore, áreas, base, refugo e pontes saem idênticos.
⚠️ Onde isto vale hoje: no motor anterior do 3D, que fica no sistema como reserva (JPCaixa3DLegado, usado sozinho se o novo não carregar). No motor que as 5 telas usam agora, quem resolve a mesma coisa é a v2.37.981, por "andares" — eu desfiz o meu porte pra lá: duas contas da mesma coisa somariam e a aba entraria o dobro (§9.13).
📏 Medido na caixa 06 da MITTO (onda 3 mm), pra quem for mexer nisso: aqui a aba fica em z −7,8 → −3,0 contra a face em −3,0 → 0 — encostada, sem encavalar. Pelos andares da v2.37.981 ela fica em −4,8 → −1,5: some a emenda que se via na face, e sobra 1,5 mm (meia espessura) de chapa dentro de chapa, porque metade do andar é absorvida pelo raio da dobra.
🔧 Por dentro: js/69-caixa3d-motor.js ganhou colarPorDentro (mede a caixa montada; só ABA sem filho colando numa CHAPA com filho, paralela de verdade até ~3,6°, encavalando na fatia e encostando mesmo; anda o mínimo, nunca mais que a espessura; "por dentro" é o lado do miolo da caixa). js/70-caixa3d.js aplica no content do painel, multiplicado pelo andamento da dobra. Teste tests/aba-de-cola-por-dentro.test.mjs (33 checagens, 8 mutações, 27 cenários com as 3 facas reais, bases diferentes e dobras ajustadas). Preview aprovado: https://claude.ai/artifact/Gi5qdX3RVzrHLHDYfBkHxM
v2.37.981
🧊
3D: A BASE SE ESCOLHE CLICANDO NA CAIXA · A ABA DE COLA VAI PRA DENTRO E AS ABAS DA LATERAL FICAM POR BAIXO DAS DO COMPRIMENTO · 📦 A ARTE NOS PACOTES DO PLANO ACOMPANHA A CAIXA.
Dono em
05/10/2026:
"quero clicar no 3D para definir a base, e assim a caixa ficar em pé como deveria" ·
"o lap ficou pra fora, tem que ficar pra dentro; as abas estão sobrepostas uma dentro da outra — as da lateral têm que ficar por baixo da aba do comprimento" ·
"na vista de cima o desenho da caixa tem que seguir a vista da caixa; tem que ficar do tamanho real, a arte tem que vestir a caixa". Previews aprovados.
✅
Base pelo clique: a pergunta "qual painel fica no chão?" virou uma
faixa em cima — a caixa fica visível e
clicar num painel já o torna a base (a caixa remonta em pé sobre ele; o giro para no primeiro clique). A lista continua atrás de "escolher na lista ▾";
✓ Está certo assim fecha a faixa e libera o 💾 se a base mudou.
✅
Andares das dobras: a aba de cola dobra um andar pra DENTRO (fica atrás da parede, como na caixa de verdade) e as abas de fechamento dos painéis
compridos fecham por FORA, um andar acima das abas da lateral — nada mais sobreposto no mesmo plano. Vale pro 3D de faca em DXF e pro da fórmula.
✅
Plano de Desenvolvimento → Paletização: na vista de cima a arte
gira junto com o pacote (pacote em pé = arte em pé); no pacote fechado, na 1ª camada e no palete completo a arte entra no
tamanho real da chapa dobrada pela mesma régua do 3D (o encaixe da arte na faca), em vez de esticada na tampa. Sem encaixe, sai a metade de sempre.
🔒
Não muda: nenhum número (pacote, lastro, camadas, peso); base e dobras gravadas no mesmo formato; caixa com base gravada abre direto, sem pergunta.
Sem Luan.
🔧 Por dentro: js/120 perguntarBase/pintarPergunta (faixa, S.perguntando), andares() no modeloDoJs69 (stack −1 cola / 1 compridas / 0 laterais); js/118 andar negativo vira deslocamento com a dobra (dz); js/19 palArteRegiao (cal + bbox da faca) e arteNoPacoteTop (rotate 90 no pacote girado); js/08 o Plano calcula a cal (jpArteCal3D) antes de desenhar o palete. Testes: palete-arte-gira-e-encaixa (15), caixa3d-novo-mapa-js69 (30), caixa3d-novo-tela (22).
v2.37.980
🧊
3D NOVO MONTA COM O MAPA DE PAINÉIS DO MOTOR ANTIGO — A FACA REAL VOLTA A MONTAR CERTA.
Dono em
05/10/2026, testando a 979 no ar com a 01.02 DEUSA (faca do ArtiosCAD):
"ficou pior, o anterior estava melhor" — a caixa montou de pé em cima de uma aba, com as abas de cima abertas, 10 painéis em vez de 13, e um pedaço solto voando no mockup.
🔎
A causa: na faca de verdade o achador de painéis do Montador tropeçou nos vincos que não encostam no rasgo; o js/69 (motor antigo) acha painéis, dobradiças, base e dobras dessa faca há meses.
✅ Agora é o
js/69 que diz a topologia (os mesmos painéis, a mesma base, as mesmas dobras do 3D antigo) e o motor do Montador só
desenha por cima: cantos arredondados, onda na borda, arte. Base e dobras gravadas são lidas e gravadas
tal qual, sem conversão. Pedaço solto não entra na foto do mockup.
🔒
Não muda: nenhum número; a tela e os botões da 979; textura do papel; mockup fechado. Conferido com as facas reais dos testes (mitto-06: 15 painéis, parmegiane: 17) e a maleta da fórmula (13).
Sem Luan.
🔧 Por dentro: js/120 modeloDoJs69(daFaca(...)) no lugar do panelsFromEnts pra faca do sistema (o Montador continua com o dele pro desenho editado); base = índice do js/69, dobras = no.chave; teste novo tests/caixa3d-novo-mapa-js69.test.mjs (26 checagens, 2 mutações).
v2.37.979
🧊
TODO 3D NO PADRÃO NOVO: CANTOS ARREDONDADOS EM TODO LUGAR, TEXTURA DO PAPEL NO CADASTRO, MOCKUP FECHADO.
Dono em
05/10/2026:
"essa foto está com os cantos vivos, eles têm que ser arredondados — deixa tudo no padrão novo!" ·
"no cadastro de papel tem que ter um lugar para colocar a textura de kraft para sair nos modelos em 3D" ·
"a caixa tem que estar fechada nesse mockup". Preview aprovado antes de codar.
✅
Os 5 lugares que abrem o 3D (Cadastros → Caixas → 🧊 Ver e ajustar em 3D; orçamento → 🧊; Corte e Vinco → 3D; Desenvolvimento → 3D; a foto do mockup do Plano) passam a usar o
motor do Montador: dobra arredondada pela espessura, onda na borda, arte na face impressa. A tela "Ver e ajustar" mantém os botões de sempre: ◀ Desmontar e a barrinha, ⏸ girar, 📄 papel, 🎯 base,
clique numa aba pra escolher 0° / 45° / 90° / 135° / 180° e "usar como base", 💾 Salvar dobras e base, e a pergunta da base antes de montar na caixa que ainda não tem a dela.
✅
O que já está gravado continua valendo: as dobras e a base das caixas (e dos itens do Desenvolvimento) são lidas e gravadas no formato de sempre. A faca do cadastro deixa o vinco da aba parando antes do rasgo arredondado; o motor novo
costura essa ponta até o corte, senão a maleta montava com 5 painéis em vez de 13.
✅
Cadastros → Papéis → 🧊 Textura no 3D: pelo tipo (Kraft → kraft · Branco → branco), kraft, branco ou
foto própria do papel (📷 enviar uma imagem; fica guardada no cadastro, pequena). O 3D usa sozinho o papel da
capa de fora da chapa; o select "papel" das telas virou
automático, com kraft/branco à mão. A arte é impressa por cima do papel (como antes no kraft).
✅
Mockup do documento (Plano de Desenvolvimento / Plano de Carga): a caixa sai
fechada, de canto, no branco.
🔒
Não muda: nenhum número (chapa, poses, refile, peso, preço, faca, DXF). O 3D antigo fica no código (
JPCaixa3DLegado), só deixa de ser chamado; sem o novo carregado tudo volta pro antigo sozinho.
Sem Luan.
🔧 Por dentro: js/120-caixa3d-novo.js novo (JPCaixa3DNovo, mesma porta do js/70: abrir/fechar/foto/vestir/carregarThree; chaveDaDobra, baseDoIndice/indiceDaBase por centroide com o js/69, costurar, jpTexturaDoPapel/jpTexturaDaChapa); js/118 criarMotor3D (fábrica com contexto, exportada em JPMontador.motor3D), arteNoPapel, papel automático; sistema.html troca window.JPCaixa3D no fim; js/08 modal do papel + chapaId nos chamadores; js/101 chapaId. 5 testes novos (82 checagens). Plano e entrega em cartonagem2-docs/montador/. Preview: https://claude.ai/artifact/6GwKqpCQXyoWhnVcjM2NPc
v2.37.978
📜
DESENVOLVIMENTO: AS VERSÕES A-B-C DE UMA PROPOSTA FICAM DENTRO DE UM CARTÃO SÓ.
Dono em
05/10/2026, vendo a DEUSA ALIMENTOS na lista:
"os desenvolvimento a-b-c tem que estar dentro um do outro, tem que mostrar a versão que está, porém como histórico dentro do outro!". O mesmo orçamento puxado pro Desenvolvimento de novo ganha letra (ORC-0040 em 10/09 com 1 caixa e a amostra AM-0040.1; ORC-0040-A em 05/10 com 2 caixas) — e a lista mostrava dois cartões soltos, com a 01-01 MOD 2 duas vezes, sem dizer qual era a atual.
✅ Propostas com o mesmo número-base viram
um cartão: a versão atual (a letra maior) na frente, com selo "versão atual · A" e as caixas dela; as anteriores ficam dentro, no
📜 Histórico (nasce fechado, abre num clique), cada uma com número, data, etapa, caixas, amostra enviada e o próprio "Abrir". Busca e filtro por etapa enxergam todas as versões: se só a anterior casou, o cartão aparece e ela fica marcada no histórico.
🔒
Não muda: nenhuma proposta é apagada, juntada ou renumerada; a ficha aberta de cada versão, o link do cliente, o orçamento e o app do vendedor são os mesmos; os contadores do topo seguem contando as caixas de todas as propostas.
Sem Luan.
🔧 Por dentro: js/34 devNumeroBase / devLetraVersao / devAgruparVersoes(lista, DEV_PROPOSTAS) (puras) + devLinhaVersaoAnterior; devCardProposta(p, anteriores, casou) (chamada antiga só com a proposta segue valendo); as duas portas da lista (devRenderLista e devRenderSoLista) passam pelos grupos. 21 checagens e 3 mutações em tests/desenvolvimento-versoes-aninhadas.test.mjs; o dev-busca-nao-inverte passou a recortar as funções novas. Preview aprovado: https://claude.ai/artifact/GVqqrp5rLy2grsgRq2F6sC
v2.37.977
📐
QUANDO O ORÇAMENTO VIRA PEDIDO, A MEDIDA NOVA VAI PRO CADASTRO DA CAIXA.
Dono em
05/10/2026 (DEUSA ALIMENTOS · ORC-0040 · 01-01 MOD 2): o cliente mudou a medida, ele corrigiu no orçamento e perguntou onde mais tinha que mudar. A resposta era: no cadastro da caixa, na mão — porque na hora de gerar o pedido a caixa que
já existia em Cadastros → Caixas recebia só arte, faca, velocidade e fechamento; a medida ficava a velha, calada. E a Carteira, a ficha e o tablet leem o
cadastro, não o item do orçamento: a fábrica riscava pela medida velha com o preço da nova.
"então quando virar pedido tem que atualizar a medida no cadastro também" — "atualiza e avisa".
✅ Ao gerar o pedido (botão 📋 ou o aceite automático pelo link), a caixa que já existe recebe a medida interna C×L×A e a chapa do item do orçamento quando forem diferentes (corte e vinco: chapa interna e refile junto). O aviso de "pedido gerado" diz
de → para e, se a mesma caixa tiver outro pedido vivo de antes, lista o número pra conferir. O modal da caixa mostra "🔄 Medida veio do orçamento nº N · quando · quem · de → para".
🔒
Não muda: nenhum preço (o pedido já nasce com o preço travado do orçamento); pedido que já existe não é regravado; caixa nova continua nascendo igual; editar o orçamento sem virar pedido não encosta no cadastro; medida igual = nada acontece; a medida velha fica guardada (Regra Zero).
Sem Luan.
🔧 Por dentro: js/08 orcMedidaProCadastro (pura: só troca campo que o item tem > 0 e diferente; medidasAnteriores + medidaDoOrcamento na caixa), chamada no orcParaPedidoConfirmar antes da caixa nova; preencherFormCaixa mostra a origem e salvarCaixaModal preserva o histórico (a marca sai se a medida for mexida na mão). 17 checagens e 3 mutações em tests/medida-do-orcamento-no-cadastro.test.mjs. Preview aprovado: https://claude.ai/artifact/5GRxzsNj3hokrsYyNPz7Ee
v2.37.976
🧱
MONTADOR: O FILTRO DA ONDA NA ABA CARTÃO PASSA A ACHAR AS CHAPAS.
Dono em
05/10/2026, testando a 973 no ar:
"o filtro não está funcionando!!!" — com a onda EB marcada dizia "nenhum cadastrado na onda EB, mostrando todos" e logo abaixo aparecia o ONDA EB 639 com "onda EB".
🔎
A causa: a onda gravada nas chapas não é letra por letra igual à sigla do cadastro de ondas (espaço ou maiúscula/minúscula a mais, cadastro antigo) e o Montador comparava letra por letra. O resto do sistema já sabe disso:
ondaConfigDe compara sem espaço e sem caixa.
✅ O Montador compara do mesmo jeito: os chips de onda filtram os cartões de verdade, e clicar num cartão grava no projeto a
sigla certa do cadastro de ondas, não o texto gravado na chapa.
🔒
Não muda: nenhuma chapa é regravada (Regra Zero); nenhum número; o fluxo de clique da 973 é o mesmo.
Sem Luan.
🔧 Por dentro: js/118 ondaNorm / ondaIgual / ondaChave; o teste montador-clique-avanca passou a cadastrar chapas sujas ('B ' e 'c') e tem mutação pro filtro. Preview: https://claude.ai/artifact/TZbyBQ5jKqGCewgPqvqa2S
v2.37.975
🧊
O 3D ABRE JÁ COM A CAIXA MONTADA.
Dono em
05/10/2026, com a foto de uma caixa com os painéis soltos no ar:
"o 3D não monta como deveria" — e depois, escolhendo:
"tem que abrir já fechada".
🔎
O 3D montava certo. Abri a janela de verdade aqui e conferi: a caixa fecha, inteira. O que ele fotografou foi o
meio da animação — a janela começava com a chapa
plana e levava alguns segundos dobrando até fechar, e quem olha no meio do caminho vê painéis soltos e lê aquilo como caixa montada errada.
✅
Agora abre com a caixa pronta. A dobra continua à mão, quando você quiser:
◀ Desmontar e a barrinha abrem a caixa passo a passo, como sempre.
🎯
E o passo da base ficou usável: numa caixa de 13 painéis a lista passava da tela e o botão
Montar a caixa saía embaixo da rolagem — agora só a lista rola e o botão fica sempre à vista. Cada painel aparece pela
medida (529 × 278 mm, 529 × 107 mm) em vez da área: "à direita · 147.062 mm²" se repetia e não identificava nada.
🔒
Não muda: nada do desenho, das medidas ou das dobras · a foto do 3D que vai no Plano de Desenvolvimento (ela já montava a caixa antes de fotografar).
Sem Luan.
🔧 Por dentro: js/70 — tAtual começa em 1 (montada) em vez de 0; .qb .cx virou coluna e .qb .lst ganhou a rolagem (§16.6: ação que não se acha não existe); medidaDe(p) escreve a medida do painel. Conferido no navegador de verdade, num laboratório local com o js/69 + js/70 e o three do próprio repositório — foi ele que mostrou que a caixa fecha e que o problema era a animação. Teste tests/moldura-base-pacote.test.mjs: 32 checagens, 16/16 mutações (a m14 devolve a animação e a m15 esconde o botão).
v2.37.974
📐
A ARTE QUE VOLTA DO ILLUSTRATOR PARA DE SER ACUSADA · A BASE SE ESCOLHE ANTES DE MONTAR · O PACOTE DO PLANO GANHA DESENHO.
Três coisas que o dono levantou em
05/10/2026, depois que o EPS passou a abrir no Illustrator (v2.37.971).
🚨
1 · "está falando que está fora da moldura" — era defeito meu. Ele baixou a faca, encaixou a arte, devolveu o .ai e levou ⚠️. O que o sistema
entrega não é a faca: é a
prancheta (a faca
mais a folga dos quatro lados, onde moram as cotas), e o aviso comparava só com a faca — ou seja, mandava fazer o que ele já tinha feito. Medido no arquivo dele:
1.584,4 × 559,4 mm contra uma faca de
1.517 × 492. Agora valem as duas, e quando a medida for outra o aviso
diz as duas que valem. ⚠️
O 3D nunca errou nisto — a arte já caia certa (margem de 33,7 mm pra fora, dos dois lados).
🎯
2 · A base, antes de montar (
"quero selecionar elas antes de montar em 3D"). A caixa montava com o palpite e a pessoa corrigia vendo ela deitada. Agora o 🧊
Ver e ajustar em 3D pergunta
qual painel é o fundo, já marcando o que a faca indica, e só então monta.
Caixa que já tem base gravada não pergunta — seria um clique a mais toda vez.
📦
3 · O pacote do Plano (
"tem que aparecer o pacote com a quantidade que é determinada" ·
"tem que ir com a arte do .ai também"). A página 2
pedia esse desenho desde que o Plano nasceu e
ninguém nunca o produziu: saia escrito "sem desenho" ao lado de PEÇAS 25 · PESO 8,89 kg. Agora sai o pacote fechado, com os riscos das
peças de verdade (25 — não o número que cabe no desenho), as fitas e a
arte deitada na tampa.
🔒
Não muda: a faca, as medidas, o EPS, o PDF e o DXF · onde a arte cai no 3D · o 🎯 usar como base e o 💾 Salvar dobras e base, que continuam onde estavam · o kraft (que já era o padrão) · e o
palete, onde os riscos do pacote seguem sendo os que cabem no desenho (25 em 30 pacotes viraria borrão).
Sem Luan.
🔧 Por dentro: js/106 pranchetaDaFaca() + o estado ok-prancheta (a folga sai da MESMA conta do jpFacaEps/jpFacaPdf); js/08 e js/101 passaram a pintar por r.ok e não pelo NOME do estado. js/70 perguntarBase(seguir) + o.baseConfirmada (só a base GRAVADA pula a pergunta; sem painéis ou sem a tela, MONTA — a pergunta não vira porta trancada). js/19 palSvgPacote(r, {arte}) reusando drawPacoteIso/arteNaTampaIso (desenho novo nenhum, §9.13) e drawPacoteIso ganhou o parâmetro opcional divs. Teste novo tests/moldura-base-pacote.test.mjs — 28 checagens, 13/13 mutações (a m1 reproduz o aviso acusando a arte certa do dono); faca-em-eps 105/22.
v2.37.973
🧱
MONTADOR: O CLIQUE ESCOLHE E JÁ PASSA PRA PRÓXIMA ABA.
Dono em
05/10/2026, testando no ar:
"tem que ser selecionável — clico na Slotter e ele já vai pra escolha do cartão, e assim por diante". Preview aprovado antes de codar.
✅
1 Máquina: clicar no cartão da máquina escolhe
e vai pro Cartão (antes só marcava de roxo e ficava na aba).
✅
2 Cartão: a onda virou
chips e os cartões do cadastro viram
cartões clicáveis (código · onda · gramatura · R$/kg), filtrados pela onda; clicar no cartão (ou em "só a onda, sem cartão")
vai pro Modelo. Trocar a onda só filtra, porque ainda falta o cartão.
✅
3 Modelo: clicar no F0201 (ou num modelo do catálogo)
vai pras Medidas.
✅
4 Medidas:
Enter em C, L ou A com as três preenchidas leva pro Desenho 2D (digitar não pula sozinho, senão pulava antes de terminar o número). Das abas 5 a 8 nada muda.
✅
Menu da esquerda: a aba decidida ganha
✓ verde e o que você escolheu fica
escrito embaixo do nome (ex.: "🖨️ Máq. B Slotter", "onda B · KK 125/110/125", "F0201 · maleta", "525 × 210 × 270 mm"); clicar numa aba anterior volta pra trocar. ‹ Anterior e Próximo › continuam.
🔒
Não muda: nenhum número (chapa, poses, refile, peso, preço) e o que vai pro cadastro / orçamento ao Salvar. Caixa que já tem máquina e onda abre com a máquina marcada: você confirma com um clique e já avança.
Sem Luan.
🔧 Por dentro: js/118 escolhidoDa(aba) (✓ + rótulo em #mt-esc-*), PAINEIS.cartao com [data-onda]/[data-cart] no lugar dos selects, P.cartaoOk no projeto, escolherModelo → Medidas, Enter em #mt-C/L/A/d4. Teste novo tests/montador-clique-avanca.test.mjs (26 checagens, 4 mutações acusadas, DOM de mentira que lê id e data-*). Preview: https://claude.ai/artifact/MyLGKBxepAzUgFXPEDNHAf
v2.37.972
🧱
MONTADOR DE CORTE E VINCO (FASE 1): A CAIXA NASCE DENTRO DO SISTEMA — MODELO FEFCO, MEDIDAS, DESENHO 2D EDITÁVEL, 3D COM A ARTE E A FACA EM DXF, SEM SAIR DO CADASTRO.
Dono em
05/10/2026: o protótipo "Montador FEFCO v0.20" (feito fora do sistema) entrou no cadastro da caixa e no orçamento, pelo prompt v1.1 e o levantamento do Corte e Vinco (
cartonagem2-docs/montador/).
✅
Cadastros → Caixas → Corte e Vinco: botão
🧱 Montar modelo abre o Montador em tela cheia, em 8 abas:
1 Máquina (as de fábrica e as cadastradas, com a função e os limites do cadastro — fora do limite avisa, nunca barra),
2 Cartão (ondas do cadastro, chapa, papel),
3 Modelo (11 motores FEFCO: 0200–0206, 0300/0301, 0427, 0453 + a biblioteca do catálogo, com ★ nos mais usados),
4 Medidas (C × L × A, interna/externa, cantos, sentido da onda, poses, gap, refile; a chapa sai pela MESMA conta de sempre — 0201 335×245×245 onda B = 1218 × 499),
5 Desenho (editor 2D: linha, retângulo, círculo, arco, aparar, estender, offset, chanfro, raio, medir, cota, texto, ponto zero, tipo de linha, camadas, Ctrl+Z),
6 3D (monta com dobra arredondada, kraft ou branco, aberta/fechada, e
veste a arte da caixa na face impressa),
7 Salvar e
8 Arte (PDF/EPS/DXF/SVG da faca pelo 📐 de sempre).
✅
Salvar devolve o desenho pelo caminho que já existia: o DXF entra pelo mesmo "DXF da faca", poses/refile/máquina vão pro cadastro, e o 3D, a faca e o palete continuam lendo o DXF como sempre. A caixa guarda o projeto pra
reabrir e editar (um DXF importado de fora abre como desenho manual, editável).
✅
Orçamento → item → 📐 Projetar: botão
➕ Criar modelo do zero abre o Montador por cima; ao salvar, a rota vira Corte e Vinco (Slotter ou Die Cut pela
função da máquina, não pelo nome) e o item recebe poses e refile.
✅ Máquina cadastrada (ex.: Die Cut) agora decide a rota pela função cadastrada (v898), não pelo nome; e o refile não some da chapa quando o projeto veio do Montador.
🔒
Não muda: a biblioteca antiga e o "desenho real" saíram da
tela mas ficam no código (Regra Zero, chave
CV_LEGADO_NA_TELA); nenhum número de caixa já cadastrada muda; nada nos apps; o 3D das outras telas é o mesmo.
Sem Luan.
🔧 Por dentro: js/118-montador.js novo (window.JPMontador, 0 cor literal; tokens --papelao-* novos no css/00-tokens.css); js/23 cvMontadorAbrir/cvMontadorReceber + cv.montador no bloco; js/08 recalcularCaixa (refile com Montador) e orcRotaDaCaixaCadastro (função via jpFuncoesDaMaquina); js/70 exporta carregarThree; js/106 exporta jpBaixarArquivo. DXF interno = camada Design + cor 62 por entidade (1 corte · 2 vinco · 3 picote), Y pra cima, sem cota/texto. 6 testes novos tests/montador-*; suíte 476/494 (5 vermelhos pré-existentes de outras frentes). Entrega: cartonagem2-docs/montador/ENTREGA_fase1_v1.0.md.
v2.37.971
📐
O EPS DA FACA ABRE NO ILLUSTRATOR, COM AS LINHAS EDITÁVEIS — IGUAL AO DO ARTIOSCAD.
Dono em
05/10/2026:
"ele fica pensando e nao abre, mais no photo shop abre" ·
"faz o EPS de verdade igual o artioscad" ·
"o eps tem que ir com linhas editavel assim como a do artios".
🔎
A causa, e ela desmente o que eu tinha concluido em setembro: o Illustrator
não interpreta PostScript. Ele abre EPS reconhecendo o
formato dele — e o que o ArtiosCAD exporta não é "um EPS": é um
documento do Illustrator 8 com 1.290 linhas de código da Adobe no começo. O Photoshop abria o nosso porque
rasteriza (e aí nada fica editável).
✅
Agora o arquivo é esse documento: mesmo prólogo, mesmo vocabulário de desenho, mesmo fim de linha —
zero desvio do arquivo dele (nenhum operador, nenhuma linha de cabeçalho a mais). Corte, vinco, picote e cotas viram
swatch com nome, como o
Artios_Recortar: "Selecionar ▸ Mesma ▸ Cor do traço" pega a faca inteira de uma vez.
🔬
Conferido no Illustrator 2026 deste Mac, abrindo o arquivo de verdade:
171 linhas vetoriais editáveis, 15 textos,
0 imagem rasterizada e a prancheta exata (4.491 × 1.586 pt).
🔒
Não muda nada no desenho: mesma faca, mesmas medidas, mesmas cores, mesmo botão. Na caixa
01.02 DEUSA ALIMENTOS 525×210×270: painéis 35 · 529 · 212 · 527 · 214, faixas 107 · 278 · 107, faca 1.517 × 492 — idênticos ao arquivo exportado hoje de manhã. O
PDF (camadas FACA / COTAS / ARTE) e o
DXF da facaria continuam iguais.
Sem Luan.
🔧 Por dentro: arquivo novo js/119-eps-ai8.js (os seis procsets da Adobe, cópia byte a byte — não editar, não reindentar); jpFacaEps reescrita no dialeto AI (w/J/j/d + cor nomeada X + m/L/S; texto To…Tp/Tf/Tx/TO com /_ArialMT e preenchimento k), cabeçalho %%Creator: Adobe Illustrator 8.0 + %AI5_ArtSize, BoundingBox com decimais e sem HiRes, CRLF e trailer com os terminate — tudo conferido contra o arquivo dele por comparação byte a byte (operadores, chaves de cabeçalho, fim de linha). A 1ª tentativa de hoje ainda não abriu porque eu tinha posto 3 coisas que ele não usa (grupo u/U, preenchimento x, LF). Teste tests/faca-em-eps.test.mjs virado do avesso — 104 checagens, 22/22 mutações, com a lista FECHADA de operadores permitidos; faca-em-dxf ganhou o js/119 no sandbox (§9.11a). Histórico do engano: v899 camadas sem procset · v900 /Separation · v901 %AI5_ArtSize solto · v904 "nivel 1 puro".
v2.37.970
🚚
CAMINHÃO PARADO PELA OFICINA (FORA DA ESCALA) SEGURA O "SAÍ DA FÁBRICA" DO MOTORISTA.
Dono em
05/10/2026:
"checklist feito tem que deixar o motorista seguir viagem; só não deixa quando o caminhão estiver fora da escala — só se for grave".
🔎
Como era: ✗ comum já liberava e item grave já segurava (v956). Mas o
"🚫 Caminhão parado (fora da escala)" marcado pela Oficina só segurava a
Escala (não deixava escalar): se o caminhão já estava escalado, o motorista conseguia apertar "Saí da fábrica".
✅
App do Motorista: com o caminhão parado pela Oficina, o "Saí da fábrica" (da carga e da viagem) não vai — "🔧 ATN5I22 está na oficina (fora da escala) — não sai até a oficina liberar · previsão 07/10". A faixa vermelha do cartão também diz que não sai. Resolver (ou desmarcar o parado) libera sozinho.
🔒
Não muda: ✗ comum segue liberando; grave segue segurando e indo pra oficina; a Escala segue não deixando escalar caminhão parado.
Sem Luan.
🔧 Por dentro: js/116 podeSair(lista, placa, ymd, chamados) ganha o 4º parâmetro (motivo parado, com parado = o registro de caminhoesParados); motorista ckPodeSair passa MANUT. Teste em tests/checklist-pendente-todo-dia.test.mjs (seção 8). Preview aprovado: https://claude.ai/artifact/6oygVwqQ4EnK1P7rirLpRE
v2.37.969
🏭
RETORNO DE BOBINA VAI PRO ESTOQUE; ALMOXARIFADO É O QUE O ALMOXARIFE RECEBE E O QUE O COMPRAS MANDA RETIRAR.
Dono em
05/10/2026, print do app do Motorista ("Retorno (carga) · BOBINAS · PAULISPEL · → Almoxarifado"):
"onde está escrito Almoxarifado tem que ser Estoque, porque é bobina! As coisas que vão pro almoxarife e as que o Compras solicita a retirada [é que são Almoxarifado]".
✅
Sistema → Escala → retorno: o destino virou lista (🏭 Estoque · 🗄️ Almoxarifado · 📦 Área reservada da Expedição) e
acompanha o tipo: "Retorno — carga" (bobina, cimento) vem
Estoque; "Coleta — produto" (tinta, graxa, clichê, peça) vem
Almoxarifado. Pode trocar.
✅
Compras: retirada pendurada na viagem e retorno criado de uma OC seguem a mesma regra (carga → Estoque, produto → Almoxarifado).
✅
App da Expedição: no retorno de carga o botão de "tirei e deixei em" é
🏭 Estoque (produto continua 📥 Almoxarifado / 📦 Área).
App do Motorista, Escala e sistema mostram o destino certo.
✅ O retorno
BOBINAS · PAULISPEL que já existia passa a aparecer
→ Estoque: retorno de carga gravado com o padrão antigo "Almoxarifado" é lido como Estoque (nada regravado).
🔒
Não muda: nada no almoxarifado, no estoque de bobinas ou na OC — é só o destino escrito na ficha do retorno.
Sem Luan.
🔧 Por dentro: js/115 JPRoteiro.destinoPadrao(tipo) / destinoRetorno(c) / DESTINOS_RETORNO; sistema #col-destino virou <select> e colAplicarTipo troca o padrão (respeita quem já mexeu, data-tocado); painel_compras usa destinoPadrao; painel_expedicao expDestinoRetorno (não carrega o js/115). Teste tests/retorno-estoque-x-almoxarifado.test.mjs. Preview aprovado: https://claude.ai/artifact/1B9upaTBuAWheKKoRanTAE
v2.37.968
👷
ENCARREGADO COM MAIS DE UM SETOR — E A MECÂNICA (ELÉTRICA, OFICINA) NO APP DELE.
Dono em
05/10/2026:
"no app do encarregado tem que ter a opção da mecânica também, pro responsável da mecânica saber o que está acontecendo; e ele tem que poder escolher mais de um setor" ·
"o encarregado da mecânica pode solicitar as peças daquele caminhão através da solicitação do motorista, assim o motorista fica sabendo se foi feito ou não".
✅
Cadastros → Encarregados: o setor virou
caixinhas (um ou mais): Chapa, Cartonagem, Micro, Facão +
⚡ Elétrica, 🔩 Mecânica, 🚛 Oficina. Lista mostra "📦 Cartonagem · 🔩 Mecânica"; KPI 🔧 Manutenção conta quem acompanha alguma equipe. Cadastro antigo (um setor) continua valendo igual.
✅
App do Encarregado: cabeçalho com os setores;
Solicitações com chip por setor (🔩 Mecânica · ⚡ Elétrica · 🚛 Oficina · "abertos pela Cartonagem" · todos, com contagem), contadores
abertos · ninguém pegou · em andamento · esperando OK, e em cada chamado
quem está atendendo e há quantos dias ("ninguém pegou · há 3 dias" / "atendendo: MAYCON desde 25/06"); abertos antes dos resolvidos.
Produção soma os setores de produção dele (chip pra filtrar); quem é só de manutenção não vê a aba.
✅
🛒 Pedir peça deste chamado nos chamados abertos das equipes dele: a OC vai pro Compras amarrada ao chamado (
chamadoId + placa), aparece no card com o andamento (solicitada · comprada, chega dia · chegou) — e o motorista vê e é avisado no checklist dele (v967). A faixa 🛒 COMPRADO (v963) vale pra OC de qualquer setor dele.
🔒
Não muda: o encarregado
olha; atender e resolver segue sendo do mecânico no JP Manutenção / JP Oficina. Nada nos apps do Operador, Manutenção, Oficina, Compras.
Sem Luan.
🔧 Por dentro: js/09 SETOR_ENC +3, encSetores/encSetoresTxt/encMarcarSetores/encSetoresMarcados, grava setores e setor = o 1º; sistema.html #enc-setores. App: SETORES_PROD/SETORES_MANUT, meusProd/meusManut, SOL_F/PROD_F, solChamadoNoChip, solLinhaAndamento, solPecasHTML, abrirSolicDoChamado (OC com chamadoId). Teste tests/encarregado-varios-setores.test.mjs. Preview aprovado: https://claude.ai/artifact/LVBEomBN78kLmbTudCsQsL
v2.37.967
📋
CHECKLIST DIÁRIO: O PROBLEMA NÃO SOME ATÉ A OFICINA RESOLVER — E O MOTORISTA SABE QUANDO O MECÂNICO PEGOU.
Dono em
05/10/2026:
"o checklist é diário: o que foi listado tem que aparecer todos os dias, coloca a data que foi feito" ·
"quando o mecânico pegar pra atender, aparecer pro motorista que a solicitação dele foi atendida e vai ser resolvida" ·
"o motorista poder consultar os checklists" ·
"a peça pedida pelo chamado, o motorista fica sabendo se foi feito ou não".
🔎
Como era: o REGINALDO apontou 6 ✗ no ATN5I22 em 02/10 às 16:01; no checklist do dia seguinte os 35 itens vinham em branco — marcar ✗ Buzina de novo criava
outro chamado da mesma buzina (id por dia), marcar ✓ parecia resolvido com o chamado aberto; e o motorista só ficava sabendo da oficina quando ela dizia "consertou".
✅
App do Motorista — checklist do dia: bloco
⚠ Pendente da oficina — já apontado antes no topo, com os ✗ de outros dias ainda abertos, "desde 02/10", texto e foto de quando foram apontados, já marcados ✗ (
✗ Continua) — e
não abrem chamado novo (é o mesmo chamado).
✓ Resolveu fecha o chamado no nome do motorista. Os outros itens continuam vindo em branco todo dia.
✅
Cada ✗ diz como está na oficina: "⏳ Oficina ainda não pegou · apontado 02/10 (há 3 dias)" · "🔧 Oficina pegou · MAYCON · 05/10 08:10 — vai ser resolvido" · "✅ Consertado 06/10 — confirme" · e a peça: "🛒 Peça pedida 05/10: Buzina 24V — 1 un · solicitada / comprada, chega 10/10 / chegou".
✅
Faixa com som até o "Vi" quando a oficina pega um chamado dele, quando diz que consertou e quando a peça do chamado dele é pedida, comprada ou chega. Só pro motorista que apontou; a 1ª abertura só semeia (não despeja aviso velho).
✅
Aba 📋 Checklists virou consulta: filtros
caminhão · motorista · período, qualquer checklist de qualquer caminhão (só leitura, com imprimir), os dele primeiro; o cartão mostra
"📅 feito em 02/10/2026 às 16:01 · REGINALDO" e o resumo "🔧 1 atendendo · ⏳ 5 esperando".
✅
Sistema → Expedição → Checklists e
JP Oficina (fila e aba Caminhões): situação "🔧 oficina atendendo" / "atendendo: nome".
🔒
Não muda: os 35 itens obrigatórios antes de sair; item grave segura o caminhão; "consertou — confere?" e a baixa do PCP depois de 3 dias; os 6 chamados do ATN5I22 de 02/10 ficam os mesmos; papel impresso igual.
Sem Luan.
🔧 Por dentro: js/116 pendentesDe / comPendentes (resposta com pendenteDe+desde) / pendentesDoDoc / resolvidosPeloMotorista / estadoChamado / resumoChamados / pecasDe / avisosOficina; chamadosDe pula pendenteDe; situacao ganha atendendo. Motorista: ckFecharChamados, ckLinhasChamado, ckProcessarAvisosOficina/renderAvisoOficina/vistoOficina (localStorage jp_mot_ofc_visto, beep('oficina')), CK_F filtros, snapshot ordens_compra. Testes tests/checklist-pendente-todo-dia.test.mjs (57). Nasceu 966 — a main tomou o número. Preview aprovado: https://claude.ai/artifact/YGBUBsVLMbjaubyYjR8pAM
v2.37.966
🏁
PEDIDO ENCERRADO COM SALDO SAI DE VEZ — NÃO COBRA MAIS "TERMINAR".
Dono em
04/10/2026, com o
24166 · NACON · 32 CAMPO VERDE na tela:
"esse pedido está falando que tem que terminar, mas ele está com encerrado. Quando dei encerrado ele tem que sair e não pode mais voltar pra ser visualizado — é como se ele fosse entregue." A Carteira mostrava a faixa
"⏸ já embarcou e não deu baixa · FALTA COLAR 147 cx na Coladeira", o selo ⏸ na linha e, dentro do pedido,
"↩️ Reabrir Coladeira · terminar 147" ao lado do
"↩️ Desfazer o encerramento" — e o pedido preso em "Pronto p/ carregar".
🔎
Causa: quando nasceu o 🏁 Finalizar com saldo (v2.37.860), ele calava só o aviso "FALTA PRODUZIR" do encerrado e deixava
de propósito o "FALTA COLAR" e o "MATERIAL PARADO" falando (achava que caixa cortada no chão merecia aviso). Só que o "FALTA COLAR" é a
mesma trava que segura o pedido fora de "Carregado" (v2.37.546: "se o botão Reabrir apareceria, o pedido não vira Carregado"). Resultado: o encerrado nunca virava Carregado, nunca chegava a Entregue, e a faixa cobrava "terminar" pra sempre.
✅
Agora, pedido 🏁 encerrado com saldo: some da faixa amarela e perde o selo ⏸ (FALTA COLAR, FALTA PRODUZIR e MATERIAL PARADO calam); os botões
🔄 Reiniciar,
🔄 Reprogramar · falta e
↩️ Reabrir etapa/corte somem do pedido; a trava solta e ele
vira Carregado sozinho em até 30 s (tudo o que produziu já saiu em carga bipada) e
Entregue quando o motorista confirma no app — ou o PCP marca na mão, como em qualquer carregado. O selo 🏁 FINALIZADO COM SALDO fica na linha.
Única volta: ↩️ Desfazer o encerramento — aí a faixa, o selo e os botões reaparecem como eram.
🔒
Não muda: nada é apagado (registros, paletes, apontamentos, qtd comprada — REGRA ZERO); ✏️ Corrigir produção continua; pedido que
não está encerrado (TCHETTO 24086, NOGUEIRA 24289) continua na faixa igual a hoje; apps do operador, expedição e motorista não mudam; sem Luan, sem script.
🔧 Por dentro: UMA conta só (§9.13) — js/01 _pedidoPodeVoltarPraProducao diz não pra fsFechado(p) (fecha as 3 portas e, por tabela, solta spFaltaFecharEtapaFinal do js/30, que usa o mesmo _reabrirEtapaInfo); js/30 spMotivoNaoCarregado ganha a porteira no topo (a condição da pergunta 4 saiu); js/01 _podeReini idem. Fail-open sem o js/100 na página. Testes tests/encerrado-sai-de-vez.test.mjs (30) + finalizar-com-saldo (59). Preview aprovado: https://claude.ai/artifact/9Tn4rpgM4FEttzoyaUKmcU
v2.37.965
🩹
CADASTRO "EMBRULHADO": MANUTENTORES E ENCARREGADOS VOLTAM A ABRIR (E O LOGIN DOS APPS).
Dono em
03/10/2026, print da faixa vermelha:
"MANUTENTORES.filter is not a function" ao abrir Cadastros → Manutentores pra cadastrar o mecânico da Oficina (e
".find is not a function" ao salvar).
🔎
Causa: o doc
manutentores no servidor não era a lista — era a lista embrulhada
5 vezes dentro dela mesma (
{manutentores:{manutentores:{…:[3 nomes]}}};
encarregados com 6), gravado assim em 28/09. Quem embrulhava era o próprio sistema: no boot a tela lia a cópia local deste PC (que é o pacote
{manutentores:[...]}) como se fosse a lista, e quando o carimbo local estava à frente do servidor subia o pacote dentro do pacote — uma camada por vez. Mesmo bug do app de Compras em 01/07 (v2.34.28), que foi consertado só nos Compradores.
Não é da v964: ela só fez a tela ser aberta. Nada se perdeu: JOAO PAULO, LEANDRO, MAYCON TORQUATRO (e MAYCON, TULIO) estavam lá dentro.
✅
Sistema: Manutentores, Encarregados e Compradores leem a cópia local e o doc do servidor descendo as camadas até a lista; na primeira vez que percebe o doc embrulhado,
regrava ele plano no servidor (uma vez, só quando precisa) — o cadastro volta a mostrar os 3 (2 ⚡ + 1 🔩) e salvar funciona.
✅
Apps JP Manutenção, JP Oficina e JP Encarregado: o login lê a lista mesmo embrulhada (igual o app de Compras já fazia) — a tela "Carregando manutentores…" que não saía do lugar volta a listar os nomes.
🔒
Não muda: nenhum nome, senha ou setor; os outros cadastros (motoristas, vendedores, operadores…) não são tocados; nada no servidor da API.
Sem Luan, sem script.
🔧 Por dentro: js/02 jpListaDoDoc(doc, chave) / jpDocEmbrulhado / jpListaLocal(pk, chave); js/09 os 3 boots trocam o JSON.parse(localStorage…) pelo jpListaLocal, setDados desembrulha e marca, onAplicar chama salvar() uma vez; apps: appListaDoDoc no lugar de doc.data().x || []. Teste tests/cadastro-embrulhado-desembrulha.test.mjs (35). Preview aprovado: https://claude.ai/artifact/KeNWbT4WHjjyZZYoTUQXsf
v2.37.964
🚛
APP JP OFICINA — A MANUTENÇÃO É DE MÁQUINA, O CAMINHÃO TEM APP PRÓPRIO.
Dono em
03/10/2026:
"a manutenção é de máquina, teria que ser separado". Até a v963 os chamados do checklist do motorista, as trocas por km e qualquer conserto de caminhão caíam na mesma fila do app da Manutenção, misturados com Slotter e Coladeira.
✅
Novo app painel_oficina.html (instalar.html?app=oficina, também na lista de apps do admin): só chamados de caminhão. Abas
🔥 Fila (agrupada por caminhão: placa, apelido, 🟢 rodando / 🚫 NA OFICINA com previsão, nº de abertos),
🚨 Urgentes,
🚛 Caminhões (cada caminhão do cadastro da Escala com a situação, chamados abertos, km da próxima troca de óleo/alinhamento, últimos consertos e "➕ Abrir chamado deste caminhão"),
✅ Resolvidos,
🛒 Peças. "Caminhão parado" + previsão + Resolver iguais aos que a Escala e o Motorista já leem.
✅
Novo chamado escolhe o caminhão numa lista (nasce
tipo caminhao, com a placa);
Pedir peça e requisição ao almoxarife saem com origem
oficina — o Compras mostra "🚛 Oficina · nome" na OC e a faixa
🛒 COMPRADO (v963) acende no app da Oficina, não no da Manutenção.
✅
Login: o mecânico de caminhão é cadastrado em Cadastros → Manutentores com o setor novo
🚛 Oficina (KPI próprio); ele entra só pelo JP Oficina e não aparece no login da Manutenção.
✅
App da Manutenção deixa de ver chamado de caminhão (fila, urgentes, resolvidos, contadores e som de "novo chamado").
✅
Sistema → Manutenções ganha o filtro
⚙️🚛 Máquinas e Oficina / ⚙️ Só máquinas / 🚛 Só Oficina; sem filtro continua mostrando tudo.
🔒
Não muda: o doc
manutencoes é o mesmo (nada migra, nenhum chamado some — só muda qual app mostra); o checklist do motorista, a trava "caminhão parado não sai" da Escala/Motorista e as trocas por km continuam gerando o chamado do mesmo jeito; o cadastro de caminhões segue no JP ESCALA.
Sem Luan.
🔧 Por dentro: painel_oficina nasceu do painel_manutencao (mesmo gravarChamado read-modify-write); iniciarDados filtra tipo==='caminhao' de um lado e !=='caminhao' do outro; ofcAgrupar/renderCaminhoes/ofcPopularCaminhoes com JPCheck.caminhoesParados; localStorage jp_ofc_*; js/08 mntFiltradas + MNT_FILTROS.tipo; js/09 SETOR_MNTR.oficina. Teste tests/oficina-app-separado.test.mjs (42). Preview aprovado: https://claude.ai/artifact/REe83cwvQyLXfcS7Yr13F5
v2.37.963
🛒
"COMPRADO" EM TODOS OS APPS QUE PEDEM COMPRA.
Dono em
03/10/2026:
"faz isso com todos os apps que têm a opção de compra" (a faixa da v962 era só do almoxarifado da cartonagem).
✅
App da Manutenção e
app do Encarregado: quando o Compras gera a OC de uma peça/solicitação pedida ali, acende a faixa
"🛒 COMPRADO · OC-0016" com os itens, fornecedor, previsão de chegada e quem comprou, com som, até tocar em "Vi" (guardado no aparelho). Na Manutenção vale pra quem pediu e pros colegas do mesmo setor (a peça é do setor); no Encarregado, pro encarregado que pediu. Compra antiga não despeja faixa ao abrir o app.
🔒
Não muda: o toast "Peça comprada" da Manutenção (v2.31.4) continua, agora com a faixa junto; a aba Compras do Encarregado com o status e o "cobrar"; a compra avulsa do próprio Compras não avisa ninguém (quem pediu é a compradora).
Sem Luan.
🔧 Por dentro: o mesmo bloco (ocEhMinha/ocProcessarCompradas/renderFaixaComprado/vistoComprado, localStorage jp_mnt_compras_vistas e jp_enc_compras_vistas) nos dois painéis, pendurado no snapshot de ordens_compra que eles já tinham; a faixa nasce no topo do #screen-app. Teste: comprado-aviso-manutencao-encarregado (12). Quem pede compra hoje: Manutenção, Encarregado, Almoxarifado da cartonagem (v962) e a compra avulsa do Compras.
v2.37.962
🛒
QUEM PEDIU É AVISADO QUANDO O COMPRAS COMPRA.
Dono em
03/10/2026:
"pode avisar quem pediu quando comprar" (era a pergunta que sobrou do preview do financeiro).
✅
App Almoxarifado da Cartonagem: quando a compradora gera a OC da solicitação dele, a solicitação vira
comprada sozinha (antes o almoxarife marcava na mão), com o nº da OC, o fornecedor, a previsão de chegada e quem comprou no card — e acende a faixa
"🛒 COMPRADO · OC-0016" com os itens, som e vibração, até ele tocar em "Vi" (fica guardado no aparelho). Ao abrir o app, compras antigas não despejam faixa; só a compra nova avisa.
🔒
Não muda: o app da Manutenção já avisava a peça comprada (v2.31.4) e segue igual; o "📥 Recebida (repõe estoque)" continua sendo do almoxarife; a OC e o Compras não mudam.
Sem Luan.
🔧 Por dentro: painel_almoxarifado_jpe escuta ordens_compra e cruza pelo deSolic (aplicarOrdensCompras: marca a solicitação + COMPRAS_AVISOS/renderFaixaComprado/vistoComprado, localStorage almox_jpe_compras_vistas, 1ª leitura semeia calada). Teste: almox-avisado-quando-comprar (11).
v2.37.961
🔎
BUSCA NO HISTÓRICO DE CARGAS + 📦
MARCOU ENTREGUE, OS PALETES SAEM DO PA NOS DOIS.
Dono em
01/10/2026:
"quero um campo de pesquisa de cliente ou motorista aqui, pra ficar fácil localizar a carga" e
"se for marcado como entregue, tem que sair do aplicativo da expedição também — dar baixa nos dois" → previews aprovados em 03/10:
busca ·
baixa.
✅
Expedição → Histórico de Cargas: campo "🔎 Cliente, motorista, placa ou nº do pedido" em cima da tabela; filtra só a lista (os 4 cartões continuam contando tudo), mostra "N cargas" e ✕ limpar; placa com ou sem traço; acento não atrapalha.
✅
PCP → Carteira → Status: ao escolher
Entregue ou
Carregado com palete ainda vivo no Estoque PA, o sistema pergunta "ainda tem N paletes (X cx) deste pedido no PA — dar baixa neles também?". OK grava a saída dos paletes no livro (origem "entregue-pcp", com seu nome) e o movimento "Saída por entrega (PA)": somem do PA
e do app da Expedição na hora. Cancelar deixa como estava. Sem palete vivo não pergunta nada.
✅
App da Expedição: pedido
Entregue não entra mais na lista do PA (seletor "Modelo da caixa", "ainda no PA deste cliente", conferência) — a mesma régua do Estoque PA do sistema. Carregado continua (pode ser parcial).
📌
O caso que mostrou isso: NOGUEIRA · CX 08 15P EXP · pedido 24132 (1.141 cx em 2 paletes, coladeira 17/09), marcado Entregue na mão em 30/09 sem carga, romaneio ou baixa — o app do expedidor dizia "2 no PA de 2". Com o "pode fazer a baixa" do dono, os 2 paletes foram baixados no livro em 03/10 (origem entregue-pcp, obs explicando).
🔒
Não muda: status, romaneio, carga, pedido; a baixa por palete e o ↩ de voltar palete; o 🚚 "Expedir lote inteiro".
Sem Luan.
🔧 Por dentro: js/10 histNormTxt/histCargaBate/histFiltrarCargas + _histLigarBusca no renderHistoricoCargas; js/30 spBaixarAoEntregar(pedido, status) (spVisaoCaixa → disponíveis → spGravarSaidas origem entregue-pcp + adicionarMovimento + spAtualizarCaixaLocal), chamado pelo bindStatusSelects do js/01; painel_expedicao paletesDisponiveisNoPA pula statusOp==='entregue'. Teste: historico-busca-e-entregue-baixa (18).
v2.37.960
🛒
A COMPRADORA VÊ A ESCALA E PENDURA A RETIRADA; O MOTORISTA RETIRA; ELA É AVISADA; A EXPEDIÇÃO TIRA E DIZ ONDE DEIXOU.
Dono em
03/10/2026:
"a compradora visualiza a escala no app de compra e ali adiciona uma retirada, com endereço, contato, o que retirar, nota fiscal; o motorista vê na escala e, quando retirar, avisa a compradora; quando chegar na fábrica, o empilhadeirista tem que saber pra tirar e destinar" → simulador aprovado:
ver o ciclo.
✅
App de Compras, aba nova 🚛 Escala: as viagens de hoje em diante (ou um período, ou todas), cada uma com o roteiro e o andamento do motorista (não saiu · saiu · chegou no cliente · voltou, lido do mesmo lugar que "Entregas ao vivo"), e o placar das retiradas: retiradas · pendentes · não deu · esquecidas. Em cada viagem,
➕ Retirada nesta viagem: no cliente que já está no roteiro (MIUCHA: "lá tem tinta pra retirar") ou num fornecedor do cadastro / outro lugar (vira parada nova, com endereço); o que retirar discriminado, contato, 📄 pegar NF (nº), OC, produto ou carga (peso), observação e a posição no roteiro. Pendurar grava a retirada no mesmo cadastro de coletas de hoje
e põe a tarefa 🛒 no roteiro da viagem; se a escala já foi postada, é alteração: o motorista recebe "🔁 SUA ESCALA MUDOU". Tirar a retirada (só antes do motorista sair) devolve pra fila "esperando viagem".
✅
Motorista: a retirada entra na sequência da parada (Cheguei → Descarreguei →
🛒 Retirei tinta → Saí) com contato, NF, OC e observação; antes de retirar ele diz onde pôs (cabine · baú · carroceria). "Não deu — pular" pede o motivo e a retirada volta pra fila. Chegou na fábrica sem marcar =
❗ esquecida.
✅
Compradora é avisada (faixa + som até o "Vi", guardado no aparelho): 📦 RETIRADO (com onde está no caminhão) · ⚠️ NÃO CONSEGUIU (motivo) · ❗ ESQUECIDA · 🏭 CAMINHÃO NA FÁBRICA · 🏭 CHEGOU, está em X.
✅
Expedição: o alerta laranja "caminhão chegou — tirar do caminhão" diz se é retirada da Compra (com OC e NF) ou retorno e onde está (CABINE/BAÚ);
"Tirei e deixei em": 📥 Almoxarifado ou 📦 Área reservada da Expedição — é isso que a Compra lê pra saber onde o material está. "Encaminhei ao almoxarifado" continua.
✅
Fornecedor pelo CNPJ (igual ao cadastro de cliente): a Receita preenche razão social, endereço, cidade, CEP e telefone; a compradora completa WhatsApp, e-mail, contato e condição de pagamento. O endereço é o que a retirada e o motorista usam (e o que ela digitar numa retirada fica salvo no fornecedor).
✅
OC pro financeiro: ao gerar a OC, além do fornecedor, o PDF vai pro 💰 Financeiro (WhatsApp/e-mail cadastrado uma vez no ⚙️ da OC), com a condição de pagamento e o CNPJ do fornecedor no papel; a OC guarda quando foi mandada e tem o botão "💰 Mandar pro financeiro" de novo.
🔒
Não muda: ↩️ Retorno SIM/NÃO da viagem; "🔄 Precisa retirar" na OC e a fila "Retiradas esperando viagem" do PCP; o "✅ Recebi" do almoxarifado; solicitações do almoxarifado e da manutenção; os 3 status da OC.
Sem Luan (só snapshots: coletas, escalas, fornecedores, dados_empresa). ⚠️ Os testes com retirada de verdade só valem quando o dono disser "tá valendo".
🔧 Por dentro: js/115 tarefas() preserva ret/coletaId/contato/nf/nfnum/oc/obs e gera a etapa retirei (🛒) + rotuloTarefa; painel_compras: renderEscalaCompras, salvarRetiradaViagem (coleta + parada/tarefa + carimbarAlteracao), cprProcessarAvisos/renderAvisosCompras, buscarCnpjFornecedor (BrasilAPI), enviarFinanceiro/configurarFinanceiro (dados_empresa.financeiro); painel_motorista: marcarEtapa retirei → coleta coletada+ondeNoCaminhao, pular → naoConseguiu (volta pra fila), volta → esquecidaEm, trava do checklist (v956 da main) na sequência; painel_expedicao: colRetirar(id, local) grava local/retiradaEm; js/08 e painel_escala: chips 🛒 e escDevolverRetiradasTiradas/vgDevolverRetiradasTiradas. Testes: compras-escala-retirada (40), expedicao-retirada-destino, escala-roteiro-lib (60), motorista-roteiro. A 959 é a escala com roteiro (nasceu 956 no branch; a main tomou 956–958 no caminho). Script scripts/zerar-compras-2026-10-03.mjs (o dono roda) zera o app de Compras com cópia de segurança.
v2.37.959
🗺️
A ESCALA VIROU ROTEIRO — O ENCARREGADO MONTA, O MOTORISTA SÓ APERTA BOTÃO.
Dono em
01/10/2026:
"vamos melhorar o nosso processo da escala" → cinco áudios →
"pode fazer". Preview aprovado:
ver o preview.
✅
Roteiro na escala (app JP ESCALA e aba Escalas do sistema): cada parada diz o que o motorista faz lá —
🔽 descarregar e/ou
🔼 carregar uma categoria. A fábrica entra sozinha no começo e no fim. ⬆⬇ reordena as paradas. Exemplo do dono: DCX (descarrega caixas, carrega aparas) → Ramenzone (descarrega aparas, carrega bobina) → fábrica.
✅
⚙️ Materiais da expedição: as categorias (caixas · aparas · bobina · paletes vazios, e o que o encarregado cadastrar: cimento…) ficam num cadastro só, no menu de baixo do app JP ESCALA e no botão ⚙️ da aba Escalas.
"Caixas (pedidos da carga)" é fixa: é a que marca os pedidos como entregues.
✅
App do Motorista — um botão por vez, na ordem: 🚚 Saí da fábrica (uma vez só) → por parada 📍 Cheguei → 🔽 Descarreguei → 🔼 Carreguei → 🚚 Saí → 🏁 Cheguei na fábrica. A linha do tempo mostra a hora de cada etapa; dá pra
desfazer a última (pergunta antes) e
pular uma tarefa com motivo ("não deu — pular"). "Descarreguei caixas" continua marcando o pedido como ENTREGUE no escritório; "Entregas ao vivo" e a Escala leem as mesmas horas de sempre.
✅
🔥 do PCP vira ⭐ no Plano de Carga sozinho: ao escolher a viagem no plano, os modelos de pedido vivo marcado como prioridade (o botão 🔥 da Carteira, v947) já nascem com ⭐ (quem monta pode tirar). O app da Expedição mostra
🔥 prioridade no cliente em Carregar por Plano; a aba Escalas mostra 🔥 ao lado do cliente com pedido prioritário.
✅
Escala alterada depois de postada: postar no grupo ou mandar pro motorista carimba a viagem como postada (versão 1 + cópia). Salvar depois disso mudando caminhão, motorista, horário ou roteiro vira
2ª versão (observação não conta): o motorista recebe
"🔁 SUA ESCALA MUDOU" com som e vibração diferentes dos de carga, faixa laranja com o que mudou até tocar em "Vi" (guardada no aparelho se o app estava fechado); o texto do grupo sai com
🔁 ESCALA ALTERADA (Nª versão · hora) + O que mudou e 🔁 na viagem; o card no sistema/app mostra "🔁 alterada — poste de novo"; o card "Caminhões da escala hoje" da Expedição ganha o selo 🔁 alterada.
✅
Sem "Bom dia" nos 3 textos de WhatsApp (grupo pelo sistema, motorista pelo sistema e pelo app): a escala sai em qualquer horário. A mensagem do motorista abre com o nome e a data e lista o roteiro com as tarefas.
🔒
Não muda: cálculo de paletes, peso e empilhamento do plano; carregamento por bipagem e o fechamento da escala pela carga; viagens já cadastradas (sem tarefas) seguem como entrega em cada parada; o módulo "Coletas no retorno" continua igual. 🔜
Fica pra depois (decisão do dono): checklist do caminhão e o que muda no carregamento da empilhadeira quando a escala altera.
Sem Luan (só snapshots: `escalas`, `entregas_status` e o novo `materiais_expedicao`).
🔧 Por dentro: biblioteca pura nova js/115-escala-roteiro.js (JPRoteiro: materiais, tarefas, etapas, aplicar/desfazer, copiaPostagem/diff/registrarPostagem/carimbarAlteracao, textos) carregada por sistema.html (antes do js/08), painel_escala, painel_motorista; destinos[i].tarefas, viagem.rev/postadoEm/postadoRev/postadoCopia/alteradoEm/alteracoes, entregas_status.entregas[v].etapas; js/08: _matApi (snapshot materiais_expedicao), escTarefasChips/escCarimbarAlteracao/escRegistrarPostagem/escClienteTemPrioridade; js/22: plcEstrelarPrioridadeDoPedido em plcHerdarEscala, pilha serializa prioridade; painel_expedicao: expSeloAlterada, 🔥 por cliente. Testes: escala-roteiro-lib (54), escala-app-roteiro (27), motorista-roteiro (33), escala-sistema-roteiro, plano-prioridade-do-pedido; os testes antigos da escala ganharam as funções novas no mundo de mentira.
v2.37.958
📐
MEDIDA INTERNA DA CAIXA AO LADO DA CHAPA, NA CARTEIRA.
Dono em
02/10/2026:
"quero que coloque a medidas internas da caixas tbm do lado da chapa" → preview aprovado:
"coluna separada, só na Carteira".
✅
PCP → Carteira: coluna nova
Medida interna, logo depois de "Medida chapa", com
C × L × A em mm lidos direto do cadastro da caixa (seção 📐 2 · Medidas internas), sem conta nenhuma — a mesma ordem do cadastro e da lista Cadastros → Caixas. Medida não preenchida não entra (nada de "× 0"); caixa sem medida interna ou pedido sem caixa vinculada mostra "—" e explica no passar do mouse.
🔒
Não muda: nenhum número, as outras colunas, o cadastro da caixa, o orçamento, o app do operador; a aba ▤ Relatório continua como está.
Sem Luan.
🔧 Por dentro: js/01-core.js (jpMedidaInternaCelula, chamada na linha do renderPCP; linha vazia com colspan="11"); sistema.html (o <th>). Teste tests/medida-interna-na-carteira.test.mjs: 12 checagens, 4 mutações.
v2.37.957
🔢
O NÚMERO DO PEDIDO QUE VOCÊ DIGITAVA E SUMIA — AGORA VAI DIRETO PRO BANCO E FICA.
Dono em
02/10/2026:
"eu estou tentando colocar numero no pedido porem eu coloco e ele some (...) acredito que memória cache, eu quero que tenha atualização direto no banco!" — com os prints da TANGARA · Água Sanitaria 12x1L Flops e da MITTO · 02 1 LITRO (ARTE 2) de volta pro "—". Já tinha acontecido em 29/09 (TANGARA CX 15: 24184 → voltou 24190 em 39 s).
🔍
A causa (não era cache): toda tela grava a
carteira inteira a cada mudança, e o servidor aceitava o número do pedido de
qualquer cópia, mesmo atrasada. Status, chapa e o resto do pedido já tinham a trava "edição mais nova vence"; o número era o único campo principal sem ela. Uma aba de fundo ou outro PC com a cópia velha regravava o número antigo (ou nenhum) segundos depois.
✅
Direto no banco: ao salvar pelo
✏️ Editar (campo Nº do pedido) ou pelo
🔢 Trocar número, o número vai na hora pro banco, só daquele pedido, sem esperar a carteira inteira. Aviso na tela:
"🔢 Pedido N gravado no banco"; se o banco não responder, aviso vermelho dizendo que NÃO gravou (não mente).
🔒
Trava no servidor (barreira 7): o número só muda se a edição que chegou é tão nova ou mais nova que a gravada — a mesma régua de status e chapa. A troca passou a carimbar a edição. Cópia velha de outra tela não desfaz mais; ela recebe o número novo no próximo ciclo.
🔒
Não muda: lugar dos botões, caixa já carregada/entregue continua sem trocar de número, número em dois clientes continua perguntando de qual, cascata pro Estoque PA e cargas em andamento.
🧰
Luan: a metade do servidor precisa do
pm2 restart jp-cartonagem-api --update-env. Até lá, o aviso vermelho "o banco NÃO gravou o número direto" é esperado (a rota ainda não aceita) e a carteira inteira segue subindo como sempre — sem a trava.
🔧 Por dentro: api/src/routes/pedidos.js (_sqlUpsertSync: num_ped por _carimboSql ≥, barreira 7; PATCH /:id aceita num_ped e faz merge de _numPed + carimbo no dados); js/01-core.js (jpNumeroPedidoNoBanco, PATCH por pedido; trocarNumeroDoPedidoAgrupado e salvarPedido carimbam _chapaEditadaEm). Teste tests/numero-do-pedido-some.test.mjs: 31 checagens, 7 mutações, upsert rodando num Postgres real (Docker).
v2.37.956
✅
CHECKLIST DO CAMINHÃO: OBRIGATÓRIO ANTES DE SAIR, COM FOTO, OFICINA, HISTÓRICO E ESCALA.
Dono em
01/10/2026, com a planilha
"01- DAF XF (QKL2H18).xlsx":
"toda vez que o motorista fizer uma viagem o caminhão tem um checklist, obrigatório, botão de checado, se tiver algo pra fazer aparecer o que fazer e tirar fotos pra ajudar a oficina" →
"relatório no app como histórico por motorista e caminhão, uma parte na Expedição como a ocorrência, caminhão na oficina fora da escala com previsão" →
"grave não viaja, vai pra oficina" →
"troca por km com aviso" →
"imprimir igual orçamento e arquivar" →
"pode fazer: uma por dia, mesma lista pra todos, aba própria, bloqueia". Preview aprovado:
ver o preview.
📱
App do motorista: na carga do dia aparece
✅ Fazer o checklist do caminhão; o
Saí da fábrica (da carga e da escala) só libera com o checklist concluído. São os
35 itens da planilha em dois grupos (cabine · externos), ✓ Conforme / ✗ Não conforme num toque; o ✗ pede o que fazer + fotos (quantas quiser) e tem a caixinha
🚫 Grave: não tem condição de viajar — grave trava a saída o dia inteiro e o caminhão vai pra oficina. Km atual obrigatório.
Um checklist por dia por caminhão. Cada toque é gravado no servidor na hora (celular quebrado não perde nada; sem sinal, guarda no aparelho e sobe depois). Aba nova
📋 Checklists com o histórico dele e 🖨️ imprimir.
🔧
App da manutenção: cada ✗ vira um chamado com placa, item, texto, fotos, motorista e km (grave = urgente, caminhão parado). No chamado a oficina marca
🚫 Caminhão parado e a
previsão de liberação;
Resolver libera o caminhão. Troca por km vencida chega como chamado preventivo e, ao resolver, a oficina digita o km da próxima troca (vai pro cadastro).
✅
A baixa em 3 passos: motorista relata → oficina resolve (foto, o que fez) → o
próximo checklist daquele caminhão pergunta "a oficina diz que consertou — confere?" (✓ fecha, ✗ reabre). Sem confirmação em 3 dias, o PCP dá a baixa na aba.
🚛
Escalas (sistema e app da escala): caminhão parado na oficina aparece apagado na lista, com motivo e previsão, e
não deixa salvar viagem com ele; faixa amarela em cima e aviso na viagem já marcada. Volta sozinho quando a oficina resolve.
💻
Expedição → 📋 Checklists do caminhão (aba nova): histórico com pesquisa por caminhão, motorista e período, contadores, cada ✗ como ocorrência com situação (aberta · na oficina · resolvida), o checklist inteiro com as fotos,
🖨️ imprimir no papel do orçamento (logo, data e hora, frota, placa, carreta, motorista, km, Conforme/Não conforme/Observação, fotos, assinaturas), 📤 CSV e ⚙️ a lista de itens editável.
🛢️
Cadastro do caminhão: nº da frota, placa da carreta, km da próxima troca de óleo e filtros e do próximo alinhamento. No checklist, a 2.000 km do limite avisa em amarelo; passou, vermelho pro motorista e chamado pra oficina.
🔒
Não muda: rota, entregas, Cheguei/Entreguei, romaneio, chamados que a oficina já abre à mão, quem pegou a carga na estrada (não é barrado).
Sem Luan — tudo em snapshot que já existe (
checklists_caminhao,
checklist_caminhao_config) e na lista
manutencoes.
🔧 Por dentro: js/116-checklist-caminhao.js (JPCheck, puro: itens, idDe 1/dia, responder/progresso/concluir, chamadosDe, podeSair, caminhoesParados/parado/rotuloParado, filtrar/situacao/resumo/csv, avisosKm/chamadosKm, papelHTML) carregado por painel_motorista, painel_manutencao, painel_escala e sistema.html; js/117-checklists-caminhao-tela.js (aba, pela API — o db é null no sistema); painel_motorista.html (tela #ck-tela, merge keyed por id em checklists_caminhao, ckPodeSair nos dois marcarSaida, aba checklists, confirmação DVIR); painel_manutencao.html (mntBlocoCaminhao, resolver zera caminhaoParado, km da próxima troca); painel_escala.html + js/08 (escParados, option disabled, bloqueio no salvar, banner); js/08 cadastro (frota/carreta/kmProxOleo/kmProxAlinhamento, persistem no dados jsonb); js/01 + js/07 (view e permissões). Teste: tests/checklist-caminhao.test.mjs (120 checagens, 3 mutações).
v2.37.955
🚨
O GERADOR DE ETIQUETAS NUNCA GRAVOU (NEM LEU) A NUMERAÇÃO NO SERVIDOR.
Dono em
01/10/2026:
"mudei o número várias vezes mas não gravou, vê pra mim por quê". Lido no servidor: contador em
clichê 24 · faca 8, sem nenhuma máquina gravada e sem o 262 — e a tela da Numeração sempre mostrou
1.
📌
A causa: a config do Gerador (contadores, máquinas, avulsas) lia e gravava pelo
db do Firebase, que no sistema é
sempre vazio desde que a API do PostgreSQL ligou (o mesmo buraco que matou a coleta na v2.37.380). O "Salvar numeração" saía calado e o toast dizia "✅" sem ter gravado. Só a reserva de número (que já ia pela API) funcionava, por isso o servidor andou até o 24 sem ninguém ver.
✅
Agora: a Numeração mostra o contador de verdade do servidor, o
Salvar numeração grava de verdade (e o ✅ só aparece depois do servidor responder; se falhar, avisa ⚠️), e a caixa nova sugere o número que está lá.
Pra fazer o que você queria: abre o Gerador de Etiquetas, coloca
262 no Próximo · Clichê (e o número certo da faca), salva, e a próxima caixa nova já abre com 262.
🔒
Não muda: nenhum contador foi alterado por esta versão (o 24 · 8 continua até você ajustar), caixas e etiquetas já feitas, o balcão de reserva da API.
Sem Luan.
🔧 Por dentro: js/18-etiquetas.js ganhou _lerConfig()/_gravarConfig() (GET e POST /merge de /api/snapshots/etiquetas_config via apiFetch quando usarApi(); o db fica de tábua pros painéis com o shim); carregarEtiqConfig, salvarEtiqConfig (devolve true/false) e etqSugerirNumeros passam por eles; etqSalvarNumeracao virou async e espera a resposta. O sistema.html não carrega o firebase-api-shim.js — módulo novo que falar com db no sistema fala com ninguém. Teste: tests/contador-cliche-no-cadastro.test.mjs, seção 10 (cenário fiel: sem db) + mutação 4.
v2.37.954
📆
PLANEJAMENTO E CRONOGRAMA FALANDO A MESMA LÍNGUA.
Dono em
30/09/2026:
"vamos alinhar o planejamento com o cronograma" →
"pode fazer". Preview aprovado:
ver o preview.
📌
O que acontecia (medido no dado real, 30/09 09:00): o 🏭 Cronograma dizia
1 pedido amanhã e a semana vazia; o 📆 Planejamento dizia
17, 12, 14… nos mesmos dias. E hoje: 10 pedidos numa tela, 19 na outra. Eram duas filas — a previsão do cronograma só via quem já tem programação/chapa; o planejamento punha também quem
espera programação — e o planejamento refazia o dia de hoje em vez de ler o plano congelado.
✅
Uma fila só de previsão (amanhã em diante), nas duas telas: quem tem chapa na frente, depois os programados, depois quem espera programação (🔥 prioridade, depois data) — os
sem chapa saem marcados com a faixa amarela e "⚠ SEM CHAPA LANÇADA" no mouse. O cabeçalho da previsão diz "✅ N com chapa · ⚠ N sem chapa", igual ao planejamento.
✅
O HOJE do Planejamento é o Cronograma de hoje: o plano congelado + o que aconteceu de verdade (apontamento fora do plano, parada apontada no tablet, hora extra), com as mesmas raias, cores e números. Clique no título do dia (🏭 abrir no cronograma) e ele abre o cronograma naquele dia; clique na barra abre o pedido.
🔒
Não muda: o plano congelado de hoje e o nº do tablet (só quem tem chapa ou está programado entra no plano de hoje, como sempre); a tabela da semana (capacidade) e o papel por onda; nenhum pedido, chapa ou status — só leitura. Aparelho com o cronograma velho em cache segue como era.
Sem Luan.
🔧 Por dentro: js/21 ganhou cronFilaPrevisao() (dono único da fila: elegíveis + esperando_programacao com restante, cada item com semChapa), o cronPlanoDoDia futuro planeja por ela, o bloco leva semChapa (classe .cron-lseg.semchapa na tela, box-shadow inline na impressão) e cronAbrirDia(ds); js/83 planeja por essa fila (o bloco antigo fica de reserva), o hoje vem de cronMontarDia + cronRenderLanes (guardado em dia.real) e o clique na barra é delegado no root. Teste: tests/planejamento-alinhado-cronograma.test.cjs (54: 43 checagens + 11 mutações).
v2.37.953
🔢
O CONTADOR DO CLICHÊ JÁ VEM PREENCHIDO NA CAIXA NOVA.
Dono em
30/09/2026, com o print da Numeração:
"estou colocando o número aqui mas não está gravando — quando for cadastrar uma caixa nova já aparece na sequência o número que está no contador" →
"pode fazer, cadastra a die cut junto e grava 262-A" →
"quando já tiver selecionado a máquina no cadastro!". Preview aprovado:
ver o preview.
📌
O que acontecia: o "Salvar numeração" gravava sim. Mas o contador só era gasto quando a caixa nova era salva com máquina
e com o Nº do Clichê vazio, e o número reservado ficava escondido (só na fila do Gerador de Etiquetas). Como o número era digitado na mão no cadastro, o contador nunca andava e nunca aparecia na caixa — parecia que o 262 tinha se perdido.
✅
Agora: Cadastros → Caixas → + Nova Caixa → 7 · Clichês, faca e fechamento abre com o próximo número do contador já no Nº do Clichê (lido do servidor na hora, pra nunca vir velho de outro PC). Escolheu a máquina, o número ganha a letra:
262-A. Máquina que gera faca (Corte e Vinco, Slotter + C&V, Die Cut) traz o Nº da Faca também:
001-A. Ao salvar, o número é reservado no balcão do servidor (duas pessoas salvando junto nunca pegam o mesmo) e fica gravado na caixa; o contador anda sozinho e a próxima caixa nova já abre com o 263. Se alguém pegou o 262 no meio, a caixa fica com o próximo livre e a tela avisa qual foi. Cópia de caixa (que abre "faltando o clichê") recebe a mesma sugestão, já com a letra da máquina que veio junto.
🏭
Die Cut (D) entrou no Cadastro de Máquinas do Gerador de Etiquetas (clichê + faca), junto com Slotter (B), Corte e Vinco (A) e Slotter + C&V (C).
🔒
Não muda: a tela do Gerador de Etiquetas e a Numeração (ajustar início); caixas já cadastradas (nada é renumerado); número digitado na mão continua valendo e não gasta o contador; o formato da etiqueta impressa; caixa antiga com o campo vazio não ganha número sozinha ao editar. A "1ª máquina" do roteiro da caixa é outra coisa e ficou como estava.
Sem Luan.
🔧 Por dentro: js/18-etiquetas.js ganhou JPNumSug (puro: formatar 262-A/001-A, decidir reservar-gravar × reservar-escondido × manual × nada, garantirDieCut), etqSugerirNumeros() (GET do snapshot, sem reservar) e etqAutoNumerarCaixa(caixa, sugestao) grava no campo quando a sugestão foi a usada; a Die Cut é semeada na lista salva no carregarEtiqConfig (merge sem seq). js/08: CX_NUM_SUG, cxSugerirNumero (só caixa nova / cópia sem clichê), cxAplicarSugestao, cxMaquinaEtqMudou (onchange do select), hints cx-cliche-hint/cx-faca-hint, e o salvar passa a sugestão. Teste: tests/contador-cliche-no-cadastro.test.mjs (50 checagens, 3 mutações).
v2.37.952
⏱
A MESMA PARADA NÃO CONTA MAIS EM DOBRO.
Dono em
30/09/2026:
"mede as paradas infladas" →
"pode fazer, sim, não". Preview aprovado:
ver o preview.
📌
O que acontecia: quando o turno acabava no meio do pedido, o apontamento parcial levava as paradas até ali e o Finalizar levava
as mesmas de novo. POWERDENT TIPO 07 (Slotter, 08/09): 164 min de "esperando chapa" + 10 de ajuste nos dois apontamentos, e
348 min na Produtividade, no OEE e na Manutenção, onde o certo é 174. Na Slotter eram uns 4 h a mais de parada por mês (julho 23,5 → 20,0 h · agosto 29,2 → 24,5 h · setembro 29,3 → 25,4 h).
✅
Na origem (app do operador): as paradas que vão no parcial do fim de turno ficam marcadas como enviadas, e o Finalizar leva só as novas. O total de parada do apontamento bate com as paradas que ele leva.
✅
Nos relatórios: ⚡ Produtividade, 🎯 OEE e 🔧 Manutenção por máquina passam a contar a parada repetida uma vez só. É a mesma régua do Pós-cálculo: mesmo pedido, mesma máquina e mesmo minuto de início. Julho a setembro ficam certos
sem mexer em nenhum apontamento.
🔒
Não muda: Pós-cálculo, Gráficos e Ficha do operador (já descontavam), a regra da parada esquecida (v545), quantidades e horários. Nenhum apontamento gravado foi alterado.
Sem Luan.
🔧 Por dentro: js/66-parada-esquecida.js ganhou JPParada.repetida(pp, r, pedidoId, vistos) (chave pedido|etapa|inicioIso; sem inicioIso nunca repete); js/05, js/39 e js/70 tiram a esquecida ANTES e a repetida depois (a esquecida não "gasta" a vista), sempre com fail-open. painel_operador.html: _paradasNaoEnviadas/_marcarParadasEnviadas no gravarParcialTurno e no salvarRegistroPendente. Teste: tests/paradas-repetidas.test.mjs (25 checagens, 10 mutações); a mutação do produtividade-parada-esquecida acompanhou a linha nova.
v2.37.951
📋
FICHA DO OPERADOR: a hora no tablet, a eficiência sem lançamento relâmpago, e as paradas do pedido em andamento.
Dono em
30/09/2026:
"traz pra mim a ficha do operador" →
"faz o preview dos dois consertos" →
"as paradas não estão sendo registradas na Slotter, verifica isso também". Preview aprovado:
ver o preview.
📌
O que estava acontecendo: (1) na Minha ficha do tablet a hora saía "— → —" (o servidor manda "07:51" e a tela só lia data completa); (2) a eficiência do PCP contava o parcial de 2 min (2.164 cx = 2164%) e os fechamentos pelo sensor de 1 min (10.504%) — a média de 29/09 dava 545% na Coladeira e 2.922% na Slotter; (3) as paradas ESTAVAM registradas (11 no apontamento do Miller), mas as duas fichas só liam o registro fechado: enquanto o pedido roda, nada aparece — e o pedido finalizado dias depois levava a parada de 16/09 pro dia 30/09.
✅
Tablet: "07:51 → 08:48" na Minha ficha; o pedido em andamento aparece com "▶ em andamento", "05:30 → agora", o parcial e as paradas de hoje.
✅
PCP: registro com
menos de 10 min de produção mostra "⚡ relâmpago · fora da conta" e sai da média (29/09: Coladeira 545% → 140%, Slotter 2922% → 63%); o card diz quantos ficaram fora. O pedido
▶ em andamento entra na ficha da máquina com início, "agora", parcial e as paradas de hoje (sem eficiência até finalizar). Cada parada conta
no dia em que aconteceu.
🔒
Não muda: nenhum registro, parada ou quantidade — só a leitura. Caixas, paletes, perdas, ocorrências e fotos iguais.
🧰 Luan: a parte do tablet (pedido em andamento e parada no dia) mora na API (
resumo-dia) —
pm2 restart jp-cartonagem-api --update-env, sem migration. Até lá o tablet mostra a hora (é só tela) e o resto fica como era.
🔧 Por dentro: painel_operador — _hm aceita HH:MM; renderResumoDia marca emAndamento. js/28 — FO_MIN_PROD = 10, foLinhasEmAndamento(ds) (lê STATE.progressosOperador, só hoje, tocado hoje, paradas do dia), parada filtrada por inicioIso no foMontarLinha. api/src/lib/resumo-dia.js (novo, puro: paradasDoDia, emAndamento, fuso da fábrica) usado pela rota /api/operador-app/resumo-dia (lê o snapshot progressos_operador). Teste: node tests/ficha-relampago-andamento-paradas.test.mjs (31 checagens, 5 mutações).
v2.37.950
📦
PEDIDO ÚNICO · ETAPA 2: ANTES DE COMEÇAR UM PEDIDO NUMA MÁQUINA, O QUE FICOU ABERTO NELA FECHA.
Dono em
30/09/2026:
"cada pedido é único; quando acabar o pedido tem que ser finalizado, e não deixado pra terminar depois; finaliza e o PCP decide". Preview aprovado (
"pode fazer, sim, sim, manter"):
ver o preview.
📌
O caso real: o NACON 12 MÉDIA C/ SIF-B (Miller, Slotter) pausou sozinho à 00:04 quando o Arnaldo entrou no FK 31644, e ficou
aberto. A Slotter dele já tinha sido finalizada pelo Arnaldo com 3.275 (29/09): fechar apontando as 397 do sensor contaria a mesma caixa duas vezes. Foi fechado agora
sem apontar (as 397 ficam anotadas).
✅
No app do operador, ao abrir um pedido que continua produção, ao apertar 🔧 Ajuste ou ▶ Iniciar produção: se a máquina tem pedido aberto, aparece
"📦 Cada pedido é único" com a quantidade já contada.
✅ Fechar e começar o novo ·
↩ Não, continuar o anterior · ✖ Cancelar.
✅
Três regras no fechamento: etapa já finalizada nessa máquina → fecha sem apontar; não finalizada → aponta o que ainda não subiu,
no nome de quem produziu, com "fechado por …", passando pelo teto do já apontado; fim de turno já apontado → conclui sem apontar de novo. Depois segue pra próxima máquina e, no fim, o PCP decide se volta com mais caixas (tarja da v905).
✅
Nada se apaga: o progresso ganha "fechado por … em …" na nuvem, e o tablet do dono aceita esse fechamento quando a produção dele é mais velha (não ressuscita o pedido). Cada fechamento fica registrado em
jp_fechamentos.
🔒
Não muda: continuar o mesmo pedido no turno seguinte (opção B), 🛑 Parar, 📤 Liberar parcial, a pausa automática da v918 (continua como rede quando não há gente pra responder, na partida automática do sensor). Pedido que já saiu da fábrica não aparece na janela (53 restos em 30/09).
Sem Luan.
🔧 Por dentro: painel_operador.html — _abertosNaMaquina (local + nuvem, mesma máquina, com produção, pedido ativo na lista), _fecharAbertoDaMaquina (_quantoFaltaLancar + _limitarPeloJaApontado + gravarConcluidoNuvem com o dono do trabalho; marca fechadoEm por /merge nas duas chaves do progresso), _adotarFechamentosDaNuvem (na _reconciliarProgressosComNuvem; régua = começo da produção, nunca o batimento), _exigirFechamentoAntes/_abrirJanelaFecharAntes nos 3 gestos (cartão, btn-ajuste → _iniciarAjusteDe, btn-prod → _iniciarProdDe). Teste: tests/pedido-unico-etapa2.test.mjs (29 checagens, 12 mutações).
v2.37.949
📅
CRONOGRAMA: o apontamento ABERTO aparece na raia, a parada "sem programação" apontada no tablet aparece como ⏸, e quem entrou antes do turno aparece desde a hora que entrou. 🏁
E o tablet ganhou o TÉRMINO ESTIMADO.
Dono em
30/09/2026, 07:00:
"estamos com apontamento mas sem no cronograma" ·
"o tablet do Fabricio, quando ele colocar sem programação, tem que aparecer no cronograma sem programação" ·
"a Grampeadeira entrou mais cedo, quando ela apontar já tem que aparecer que começou, mesmo sem turno, que seria extra". Previews aprovados:
apontamento aberto ·
término estimado.
📌
O que estava acontecendo: o plano de hoje (congelado 00:42) tinha o FK 31644 só na Grampeadeira ("corte já feito antes") e o Miller rodando a Slotter nele pelo sensor — sem etapa no plano, o cronograma não desenhava nada e dizia "❓ sem apontamento". A parada "falta de programação" que o Fabricio marcou no C&V ia pro banco (apontamentos_parada) e o PCP nunca lia. E a barra real era cortada no início do turno (07:00) mesmo com a Mayara desde 06:03.
✅
Apontamento aberto na raia: o pedido que o tablet está rodando (ajuste, produção ou parado) vira barra verde pulsando "▶", do início real até agora, mesmo quando o plano não previu aquela máquina pra ele. Só o progresso tocado hoje e desta máquina; com dois abertos na mesma máquina, vale o que o tablet tocou por último (uma máquina, um pedido).
✅
Parada apontada: "⏸ SEM PROGRAMAÇÃO · apontado" (ou 🛑 com o motivo) do início até agora, com quem apontou; o horário deixa de ser "❓ sem apontamento". O cronograma busca as paradas do dia a cada minuto.
✅
Hora extra: barra real (feita ou rodando) antes do turno ou depois dele não é mais cortada — só a barra PREVISTA continua presa ao turno.
🏁
No app do operador, na tela do pedido: "TÉRMINO ESTIMADO" com a hora (o que falta ÷ a velocidade do cadastro, pulando o almoço do turno da máquina), e rodando, a hora no ritmo de agora (verde no ritmo · amarelo atrasando · vermelho passou). No cartão da fila: "⏱ ~X nesta máquina · termina ~HH:MM", em sequência. Sem velocidade cadastrada, diz isso em vez de inventar hora.
🔒
Não muda: o plano congelado, os números do tablet, nenhum apontamento ou quantidade. O tablet do C&V continua sem pedido até a chapa da PAPELARIA/TANGARA ser lançada (estão "programado sem chapa").
Sem Luan.
🔧 Por dentro: js/21 — cronForaDoPlano(ds, chaves, {rawNow}) exclui por pid|maq (e pid|maq|reg quando só o registro está desenhado), lê o progresso vivo (cronPgDaEtapa) tocado hoje; cronParadasLivresBaixar/cronParadasLivresDoDia (GET /api/apontamentos?de&ate) → dia.paradasLivres, ocupa o cronVaos e desenha .vazio.pl; cronClampShow não corta estado done/run ou real:true. painel_operador — _opTurnoJanelas/_opAvancarNoTurno/_opTerminoEstimado/_renderTerminoEstimado, #prod-termino, _termSeq no cartão. Testes: tests/cronograma-apontamento-aberto.test.cjs (30 checagens, 7 mutações) e tests/termino-estimado-operador.test.cjs (31 checagens, 6 mutações).
v2.37.948
📦
CADA PEDIDO É ÚNICO — e o 59.563 da Grampeadeira foi desfeito.
Dono em
30/09/2026:
"chapa na grampeadeira está com 59.563 — de onde veio esse número?" e
"cada pedido é único; quando acabar o pedido tem que ser finalizado, e não deixado pra terminar depois; finaliza e o PCP decide se vai voltar com mais caixas ou não". Preview aprovado (
"pode fazer, 2087, medir primeiro, opção B"):
ver o preview.
📌
De onde veio o 59.563: em 16/09 o pedido 23367 (FK GRUPO 31644) foi largado aberto na Slotter com o zero do sensor marcado. Em 22/09 o Fabricio abriu e finalizou em 1 minuto, e o sensor preencheu tudo o que a Slotter rodou de 16/09 a 22/09 (≈ 56.700 caixas apontadas de outros pedidos). A Grampeadeira montou 459 paletes em cima disso.
Não foi o Jev (ele entrou em 29/09 e nunca grava quantidade).
✅
O dado: o pedido, a fila dos tablets, o overlay e a ficha de conclusão passaram a
2.087; o 59.563 fica escrito, marcado como anulado, com o motivo. Cópia antes no servidor (
backup_correcao_23367_20260930) e no Mac. O zero esquecido do
24003 FORTYS 70/92 (aberto desde 02/09 — poderia jogar ≈ 238 mil caixas nele) foi fechado.
✅
Grampeadeira: ao reabrir o pedido, os paletes são refeitos da base corrigida (17 em vez de 459); os já confirmados ficam.
✅
O sensor segue a vida do pedido: zero aberto em pedido que não está rodando fecha sozinho (a cada atualização e ao entrar no app).
✅
O tempo pausa uma vez só: sair do app / largar não soma de novo os dias parado (43 de 81 registros tinham tempo maior que a própria vida; o 23367 mostrava 1.095 h). O pedido aberto com tempo impossível recomeça do trecho de agora, com o valor velho guardado.
✅
"⏱ termina ~" com a máquina parada: "⏸ máquina parada — sem previsão" no lugar de "4.1877684553238204e+55h".
✅
↩ Voltar / ⏸ Pausar com produção aberta pedem o fechamento em TODA máquina (antes só com o 🤖 do sensor ligado) e o "⚠️ Ainda falta produzir" não tem mais o ⏸ PAUSAR — só ✅ FINALIZAR · vai pro PCP decidir.
🔒
Não muda: 🛑 Parar (almoço, puxar palete), 📤 Liberar parcial, os apontamentos. Os 43 tempos inflados antigos
só foram medidos (decisão do dono).
Fica pra próxima etapa (medir antes, pra não travar a fábrica com pedidos antigos pendurados): "outro pedido entra na máquina" e o fim de turno da opção B.
🔧 Por dentro: painel_operador.html — _palBaseCorrigida/_palAplicarBaseCorrigida (lê etapas[anterior].corrigidoEm, nos dois pontos que restauram a lista), _senFaxinaZerosForaDaMaquina (listener dos progressos + entrarApp; não passa pelo salvarProgresso pra não trocar o dono), _liberarPgProProximo só soma se não estava congelado (a mesma régua do _congelarTempoProd), _tempoImpossivelCorrige no iniciarTimer, _opTextoTermino, _sairDoPedidoPrecisaOk sem a condição do sensor. Testes: tests/pedido-unico-sensor-tempo.test.mjs (38 checagens, 10 mutações) e tests/sair-do-pedido-uma-vida.test.mjs atualizado pra regra nova (45/45, 15 mutações). Sem Luan: é só o app atualizar.
v2.37.947
🔥
PRIORIDADE NUM CLIQUE — e o tablet mostra vermelho e avisa.
Dono em
30/09/2026:
"lá no PCP quero um ícone, um botão pra falar que aquele pedido é prioridade… no app do operador ela aparece com uma borda brilhante, vermelha… um pop-up: caixa tal prioridade, caixa tal prioridade — ela fica ali pra ele pegar como primeira caixa". Preview aprovado (
"pode fazer, quando aparecer prioridade e para todas as máquinas"):
ver o preview.
📌
O que estava acontecendo: o campo Alta/Média/Baixa existia dentro do ✎ Editar e fura a fila desde a v838 — mas ninguém marcava (0 de 77 pedidos vivos como Alta) e
o tablet nem recebia o campo: a lista que o PCP publica pro operador não levava a prioridade.
✅
Botão 🔥 na linha da Carteira do PCP (e no cartão do Dashboard): um clique liga a prioridade Alta, outro desliga. É o mesmo campo do cadastro. Vale a permissão de editar pedido. Fica anotado na vida do pedido.
✅
No app do operador: o cartão prioritário ganha
borda vermelha brilhante e o selo 🔥 PRIORIDADE.
Pop-up quando aparece prioridade na máquina dele: ao entrar no app e quando o PCP marca uma nova (chega pelo caminho de sempre, ~5 s). Lista só as prioridades daquela máquina, na ordem da fila; "Entendi" fecha. Volta a cada entrada no app enquanto a prioridade estiver na fila. Vale pra todas as máquinas.
🔒
Não muda: a regra da fila (rodando → Reordenar → chapa → 🔥 prioridade → data); o pop-up não trava o app nem abre por cima de um diálogo de produção; o pedido que o operador já está rodando não vira pop-up.
Sem Luan.
🔧 Por dentro: js/01 — jpAlternarPrioridade(pid) + _btnPrioHTML (Carteira ~3156 e cartão ~1441), data-act="prio" no bindRowActs e no bindOrderActions. js/02 — limpo.prio no recorte pedidos_operador. painel_operador — prio no _construirPedidosBrutos, classe .prio-alta + .prio-selo, _prioAvisar(lista) no fim do renderListaPedidos (abre por style.display, §9.10), _PRIO_AVISADOS zerado no entrarApp. Teste: node tests/prioridade-pcp-e-tablet.test.cjs (31 checagens, 7 mutações).
v2.37.946
📆
PLANEJAMENTO: as máquinas cadastradas entram, o dia a dia sai igual ao cronograma, e QUEM TEM CHAPA VAI NA FRENTE DA FILA.
Dono em
30/09/2026:
"a Die Cut cadastrada não está aparecendo no planejamento… em cima de cada máquina o tempo que precisa, o que cabe, o quanto falta… o dia a dia igual o cronograma… e o que aparecer com chapa entra como prioridade". Preview aprovado (
"pode fazer, chapa na frente nas duas"):
ver o preview.
📌
Por que a Die Cut não aparecia: as 4 máquinas de fábrica estavam escritas fixas no Planejamento — máquina cadastrada nunca entrava. E hoje nenhum pedido vivo está nela (os 3 que passaram já foram entregues), então ela só vai aparecer quando tiver caixa lançada, como você pediu.
✅
Máquina cadastrada (Die Cut, Facão, Integrada) entra na tabela da semana, no dia a dia e na fila da chapa —
só quando tem caixa. As 4 de fábrica aparecem sempre.
✅
Dia a dia igual ao cronograma: ícone e nome da máquina, número da fila na barra (hoje é o mesmo número do tablet), cinza "⏸ sem programação", almoço e fora do turno. Embaixo de cada máquina:
precisa · cabe · sobra/falta; no topo do dia, a soma e
✅ N com chapa · ⚠ N sem chapa. No mouse, cada barra diz o acumulado até ali.
✅
Chapa lançada vai na frente: a fila do cronograma (que é a do Planejamento e do tablet) ganhou o degrau da chapa — depois de quem está rodando e da ordem do 🔀 Reordenar, antes da prioridade e da data. Um pedido com chapa passa na frente de quem ainda não tem, em qualquer status.
🔒
Não muda: as contas de tempo, velocidade e turno (são as do cronograma); o plano congelado de hoje e a numeração já publicada; o Planejamento continua só leitura.
Sem Luan.
🔧 Por dentro: js/83 — lanesCadastradas/lanesTodas (fábrica + maqProcAtivas), nomeLane/iconeLane pelo cronInfoMaq, previsaoDiaria com num/acum/comMaterial/lanesDia, quadroDias reescrito com as classes do js/21. js/21 — degrau 3 do cronPedidosElegiveis: temChapa. Teste: node tests/planejamento-maquinas-e-chapa.test.cjs (26 checagens, 7 mutações).
v2.37.945
📷
FOTO PERDIDA NÃO É ERRO DO SISTEMA — a faixa vermelha das Ocorrências era 3 fotos de 11/06 que sumiram do disco.
Dono em
29/09/2026:
"erro na ocorrencia !" (print da faixa vermelha em cima da tela ⚠️ Ocorrências:
"arquivo não carregou: foto_0.jpg" ×3,
"v?"). Preview aprovado (
"pode fazer, deixa a marca de foto perdida"):
ver o preview.
📌
A causa: conferido no Chrome do dono, só lendo: das
234 fotos de ocorrência,
231 abrem e 3 dão "não encontrado" — as três de
11/06/2026 (FK Grupo · Mancha, FK Grupo · Trinca, Nacon · Abaulada), as mais antigas com foto. O arquivo sumiu do disco e a pasta
api/uploads não tem backup. A faixa da v925 foi feita pra acusar
arquivo do programa pela metade e não distinguia: foto que não abre pintava "O sistema deu um erro" toda vez que a lista desenhava.
✅
A faixa só acusa arquivo do programa (js/css). Foto ou mídia que não abre fica só no
?diagnostico=1, como "foto não abriu: …", e não entra na lista da faixa.
✅
Foto perdida vira marca: no cartão e nos Detalhes, um quadradinho tracejado "📷 foto não está mais no servidor" (nos Detalhes com a data do arquivo perdido) no lugar da imagem quebrada; o clique de abrir em grande fica desarmado.
✅
A faixa mostra a versão (saía "v?": o
JP_VERSAO_APP do js/12 nunca era publicado em
window no sistema.html).
🔒
Não muda: nenhuma ocorrência, tipo, texto ou foto é alterado ou apagado — a URL da foto perdida continua registrada; as 231 fotos que abrem seguem iguais; a faixa continua pintando erro de programa de verdade; o piloto do Jev (v944) não é tocado. As 3 fotos
não têm como voltar pelo sistema.
🔧 Por dentro: a peneira por tagName (IMG/VIDEO/AUDIO/SOURCE) no ouvinte de error do bloco 🩹 CURA DO BOOT (fim do sistema.html) e a faixa lista ERROS.filter(ehErroDePrograma); jpOcFotoPerdida(img, dataIso, grande) no js/08, chamada pelo onerror da miniatura (renderOcorrencias) e da foto dos Detalhes (abrirOcDetalhe); window.JP_VERSAO_APP no js/12. Teste: tests/faixa-nao-acusa-foto-perdida.test.mjs (25 checagens, 2 mutações acusadas); cura-do-boot segue 27/27. De passagem: o servidor já estava na v944 — o deploy pelo GitHub voltou a funcionar.
v2.37.944
🧪
PILOTO DO JEV: A OCORRÊNCIA "❓ OUTRO" GANHA UMA SUGESTÃO DE TIPO — e o PCP decide com um clique.
Dono em
29/09/2026:
"faz o piloto das ocorrências Outro". Preview aprovado (
"pode fazer"):
ver o preview.
📌
O problema: quem registra uma ocorrência e não acha o tipo marca "Outro" e escreve. O "Outro" vira o "tipo mais comum" e não diz nada — pra saber a causa, alguém tinha que ler cartão por cartão.
✅
Em Análises → ⚠️ Ocorrências, o cartão "Outro" mostra
"💡 Parece Chapa descolando · confiança 92%" com
✔ É isso e
✕ Não é. "É isso" troca o tipo, o cartão entra no ranking certo e guarda quem trocou e que antes era "Outro". Abaixo de 80% de confiança a sugestão não aparece.
✅
Quadrinho 🧪 Piloto (só o admin vê): sugestões feitas, aceitas, recusadas, acerto e se o Jev ficou sem responder — e o botão de ligar/desligar.
✅ Vale também pras ocorrências "Outro" antigas: o robô passa por elas aos poucos (20 a cada 2 minutos).
🔒
Não muda: os apps do operador e da expedição, a pausa do pedido, a Vida da Caixa.
Nenhum tipo muda sem clique de gente. Vai pro Jev (TypeSafe AI)
só o texto da ocorrência e a lista de tipos — nunca cliente, pedido, operador ou máquina. Se o Jev cair ou demorar mais de 1,5 s, a tela fica igual a antes.
🧰
Nasce DESLIGADO. Pra ligar: Luan roda
npm run db:migrate (052), põe
TYPESAFE_API_KEY= no
.env do servidor e reinicia a API (
pm2 restart jp-cartonagem-api --update-env); depois o admin aperta ▶ Ligar no quadrinho.
🔧 Por dentro: api/src/lib/jev.js (a única porta pro Jev: timeout 1,5 s, nunca estoura), api/src/lib/jev-ocorrencias.js (o robô: listas de tipos iguais às das telas, só "Outro" com texto, teto por rodada, resposta fora da lista vira "sem sugestão"; cutucado pelo /merge do jp_ocorrencias e de 2 em 2 min), api/src/routes/jev.js (/api/jev/ocorrencias/sugestoes, /decisao, /estatisticas e /config — as duas últimas só admin), migration 052_jev_decisoes (só CREATE), js/114-jev-ocorrencias.js (chip, marca e quadrinho; troca o tipo pelo _ocGravarUma de sempre) e dois ganchos no renderOcorrencias (js/08). Testes: tests/jev-ocorrencias-servidor.test.mjs (54 checagens) e tests/jev-ocorrencias-tela.test.mjs (40), 15 mutações acusadas; rotas e robô conferidos num Postgres de verdade (Docker). ⚠️ A API de verdade devolve a decisão DENTRO de answers (o exemplo da documentação não mostra) — achado ao testar com a chave do dono; 8 textos de exemplo, 250–500 ms cada.
v2.37.943
📅
CRONOGRAMA: O APONTAMENTO FORA DO PLANO APARECE NA RAIA — e a manhã antes do plano nascer não é mais cobrada.
Dono em
29/09/2026:
"hoje tivemos várias apontamento na coladeira… está falando que não teve nada de apontamento". Preview aprovado (
"pode fazer, com a manhã também"):
ver o preview.
📌
O que estava acontecendo: o plano do dia foi congelado às 17:22. A essa hora os 5 pedidos que a Coladeira fez (07:21→16:42) já estavam prontos, e o plano só pega quem ainda falta. O cronograma só desenhava quem estava no plano — o trabalho da máquina saía como "❓ SEM APONTAMENTO" e "⏸ SEM PROGRAMAÇÃO". Slotter e Corte e Vinco: 10 dos 12 apontamentos do dia estavam fora do plano.
✅
Todo apontamento do dia aparece na raia da máquina, no horário em que aconteceu, em verde com contorno tracejado e o selo "fora do plano" (passe o mouse: pedido, horário, quantidade e operador; clique abre o pedido). Vale pro dia de hoje e pros dias passados.
✅
A hora em que a máquina trabalhou deixa de ser vão — o "sem apontamento" só fica onde ninguém apontou de verdade.
✅
Antes de o plano nascer, ninguém é cobrado: o horário anterior ao congelamento sai como "⏳ PLANO NÃO EXISTIA" (apagado), no lugar do ❓ amarelo. O card "⏸ Máquina parada" mostra esse tempo separado.
🔒
Não muda: o plano congelado, os números 1º/2º… do tablet, os pedidos do plano (mesmo lugar, mesma cor), nenhum apontamento nem quantidade. A impressão A4 sai igual à tela.
Sem Luan.
🔧 Por dentro: js/21 — cronForaDoPlano(ds, pids) (registros do dia de quem não está no plano, pela raia do js/49) e cronPlanoNasceuMin(ds), ambos no cronMontarDia (dia.fora, dia.planoNasceu); cronVaos ocupa a raia com o fora do plano e marca pn antes do plano nascer; cronRenderLanes e _cronPrintTimeline desenham pelo mesmo _cronForaTitulo. Teste: node tests/cronograma-fora-do-plano.test.cjs (35 checagens, 6 mutações).
v2.37.942
🎨
A janela "de qual cliente?" do 🔢 ficou igual ao preview.
Conferido no Chrome do dono logo depois da v2.37.941: a bolinha de escolher ficava solta no meio da linha e o nome do cliente espremido, em letra pequena e maiúscula — o estilo geral dos formulários do sistema pegava a janela. Agora: bolinha à esquerda, cliente em negrito, as caixas embaixo e o motivo de quem está travado.
🔒
Não muda: nada do que o 🔢 faz — só o desenho da janela.
🔧 Por dentro: pedNumAbrirEscolha (js/01) zera no próprio label/input o que as regras globais label{…uppercase…} e input{padding…} impõem.
v2.37.941
🔢
TROCAR NÚMERO QUANDO O NÚMERO ESTÁ EM DOIS CLIENTES — o 🔢 pergunta de qual.
Caso do dono em
29/09/2026: o pedido 24190 tinha
DCX · PARMEGIANE G e
TANGARA · CX 15 UNI LIMP ALCOOL. Levar a TANGARA pro 24184 (da própria TANGARA) era recusado com
"O número 24184 já é de TANGARA". Preview aprovado (
"pode fazer, com o selo"):
ver o preview.
📌
O que estava acontecendo: o 🔢 troca o número de todas as caixas do pedido de uma vez e pegava o cliente da primeira caixa da lista (DCX). Aí achava que a TANGARA indo pro 24184 era "outro cliente".
✅
Número com 2 ou mais clientes: o 🔢 abre uma janela com um cliente por linha. Você escolhe o cliente, digita o número novo e só as caixas dele mudam. Embaixo do número aparece o aviso: "vai ficar no mesmo pedido" (mesmo cliente) ou "já é de outro cliente" (não deixa).
✅ Cliente com todas as caixas já carregadas/entregues aparece travado, com o motivo.
✅
Selo na Carteira: o cabeçalho do pedido mostra
"⚠ 2 clientes neste número" (passe o mouse pra ver quais).
🔒
Não muda: número com um cliente só funciona como antes; caixa carregada/entregue não troca de número; Estoque PA e cargas em andamento acompanham a troca; o ✏️ Editar da caixa continua trocando só ela.
Sem Luan.
🔧 Por dentro: js/01-core.js — trocarNumeroDoPedidoAgrupado(chave, esc) agrupa por cliente e, com 2+, chama pedNumAbrirEscolha (janela criada por JS, filha do body); com esc = {cliente, novo} filtra o cliente e não pergunta de novo; devolve true quando trocou. Selo no renderGrupoPedido. Teste: node tests/numero-com-dois-clientes.test.mjs (10 checagens, 2 mutações); o pedido-lote-prioridade-faturamento segue verde.
v2.37.940
↩
TIRAR PALETE PELO ✏️ CORRIGIR CARGA DEVOLVE O PEDIDO PRO ESTOQUE PA — pronto pra pegar de novo e com o número liberado pra trocar.
Pedido do dono em
29/09/2026:
"quando eu tirar do romaneio tem que voltar para o estoque PA e fica disponível para pegar novamente". Preview aprovado:
ver o preview.
📌
O que estava acontecendo: os 5 paletes da TANGARA · CX 15 UNI LIMP ALCOOL (3.631 cx) foram tirados da carga do LUIS CARLOS GUETTI pra trocar o número do pedido e sumiram de todo lugar. O palete voltava no controle de saídas, mas o pedido continuava
Carregado — e pedido Carregado não aparece no Estoque PA, não aparece no "➕ pôr na carga" e não deixa trocar o número.
✅
Tirou todos os paletes do pedido → o pedido volta pra
Pronto p/ carregar.
Tirou só alguns (ou ainda tem palete dele em outra carga finalizada) →
Carregado parcial. Os paletes aparecem no Estoque PA na hora, e a vida do pedido anota pra onde voltou e o motivo.
✅ Pôr de volta na carga leva o pedido a
Carregado sozinho, como sempre.
🔒
Não muda: pedido que o motorista já confirmou como entregue continua barrado; o romaneio antigo continua cancelado com o número no histórico; nenhum número de caixa, peso ou preço. Os paletes tirados antes desta versão o dono devolve na mão (status do pedido → Pronto p/ carregar).
Sem Luan.
🔧 Por dentro: js/79 ganhou _voltarPedidoDaCarga, chamado pelo tirarPalete depois que a carga é regravada (servidor mudo = status não muda); refaz o PA pelo estRessuscitarPorEstorno do js/03. Teste: node tests/tirar-da-carga-volta-pro-pa.test.mjs (11 checagens, 3 mutações).
v2.37.939
✉️
TODO E-MAIL DO SISTEMA NO PAPEL DO ORÇAMENTO — branco, com a logo, igual em qualquer programa.
Pedidos do dono em
28/09/2026, com o print do comunicado de reajuste da TANGARA:
"o fundo esta escuro e as letras tbm quero tudo em um padrao so" ·
"vamos deixa no padrao o orçamento !" ·
"deixa todos padrao todos iguais !!". Preview aprovado (
"pode fazer, com a logo"):
ver o preview.
📌
O que estava acontecendo: os e-mails eram montados
escuros de propósito (fundo quase preto, letra clara), com a cor numa "caixa" que cada programa trata de um jeito: o
Outlook ignora o fundo e deixa branco com letra quase branca; o
celular em modo escuro inverte sozinho e fica fundo escuro com letra escura. O mesmo e-mail chegava de três jeitos — e o relatório do papel já era claro, então nem entre eles havia padrão.
✅
Um papel só pros 7 e-mails: comunicado de reajuste, orçamento pra aprovação, aviso pro vendedor, pedido registrado/andamento/aprovação, avisos do Desenvolvimento, troca de senha, ficha de encomenda (faca/clichê) e relatório do papel.
✅
Com a cara do orçamento: a
logo do cadastro (Dados da Empresa) à esquerda, "Caixas de Papelão Corrugado · Boracéia/SP", a linha azul embaixo e o título à direita; letra escura em fundo branco; tabela com cabeçalho cinza claro.
✅
Igual em todo programa: o branco vai preso em cada pedaço do e-mail e o e-mail avisa o celular "sou claro, não inverter".
🔒
Não muda: o texto, os preços e o percentual (vêm da tela do reajuste como antes); quem recebe; o assunto; o modo teste (a faixa continua, agora amarela e dentro do papel); nenhuma conta.
🧰
Luan: pm2 restart jp-cartonagem-api --update-env (é e-mail, sai da API). A logo só aparece se o
API_PUBLIC_URL do .env for o endereço público — sem ele, sai o nome JP EMBALAGEM em azul no lugar (nunca imagem quebrada).
🔧 Por dentro: api/src/lib/email-layout.js novo (o papelEmail + ficha, botão e tabela, cor presa com bgcolor, color-scheme: light only); o enviarEmail troca o nome pela logo antes de sair (o data:image do cadastro vira arquivo em /api/uploads/empresa/logo-<hash> — o Gmail bloqueia data:image); teste tests/emails-padrao-orcamento.test.mjs (os 7 renderizados, a logo, 4 mutações).
v2.37.938
📥
PUXAR DO DESENVOLVIMENTO PRO ORÇAMENTO — o espelho do "📄 Do orçamento" — e a caixa acrescentada depois não fica mais de fora.
Pedidos do dono em
27/09/2026:
"nós temos como puxar do orçamento para o desenvolvimento; quero poder puxar o desenvolvimento para o orçamento também" ·
"tem vários no desenvolvimento que precisa ir para o orçamento e ainda não foi". Preview aprovado:
📥 Do Desenvolvimento.
📌
O que estava acontecendo: a proposta só ia pra fila de Solicitações no momento em que NASCIA — caixa acrescentada depois numa proposta que já existia nunca entrava; e a ficha do Desenvolvimento escrevia "⏳ na fila de Solicitações" em toda caixa sem preço, sem conferir. Conferido no dado real: das 11 propostas, 9 já têm orçamento; as 2 esperando preço (0045 REVAL e 0047 TANGARA) estavam escondidas como "atendida" e foram reabertas na fila.
✅
Comercial → Orçamentos · botão 📥 Do Desenvolvimento (ao lado do "+ Novo Orçamento"): lista só as propostas
esperando preço, a que espera há mais tempo primeiro, com busca. Escolhe uma → marca as caixas (as que já têm preço aparecem travadas) →
📥 Puxar pro orçamento: o orçamento abre com o
mesmo número, cliente, vendedor, medidas, chapa e cores; só falta a quantidade.
✅
Proposta que já tem orçamento: a caixa acrescentada depois entra
nesse mesmo orçamento, como item novo (o salvar registra a revisão). Só entram as caixas marcadas que ainda não estão nele.
✅
O cartão ⏳ Aguardando preço conta as amostras pelo
próprio Desenvolvimento (não depende mais da fila, nem do "atendida", nem de a caixa ter nascido junto com a proposta); o "💰 Dar preço" de cada linha é o mesmo 📥 (uma proposta por vez). Os pedidos dos vendedores continuam vindo da fila. Sem a lista do Desenvolvimento (sem acesso/sem internet), o cartão volta a contar pela fila.
✅
A ficha do Desenvolvimento diz a verdade: "⏳ esperando preço — o comercial puxa em Orçamentos → 📥 Do Desenvolvimento", ou "🆕 acrescentada em DD/MM · o orçamento Nº X já existe — o comercial puxa ela pra dentro dele", ou "⏳ no orçamento Nº X — esperando o preço voltar".
✅
✕ não precisa de preço nas linhas do Desenvolvimento guarda QUAIS caixas foram dispensadas — a caixa acrescentada depois volta pra lista.
🔒
Não muda: o "📄 Do orçamento" do Desenvolvimento; a fila 📨 Solicitações (as amostras continuam caindo nela também); o preço voltando pro Desenvolvimento; o "✏️ lançar na mão"; nenhuma proposta, caixa ou orçamento é mudado sozinho.
Sem Luan: usa a mesma lista que a tela do Desenvolvimento já lê.
🔧 Por dentro: js/111 ganhou devEsperandoPreco (caixa sem preço, fora de orçamento pelo devItemId, não dispensada; a proposta com orçamento vem com ele), devCaixaParaSolic (a chapa vai pelo código/rótulo — o chapaId da lista é o do banco) e caixasQueFaltam (caixa sem elo nunca entra); resumoCartoes aceita a lista do Desenvolvimento. js/08: orcItemDaCaixaSolic (o miolo do orcDaSolicitacao, agora um só pros dois caminhos, com as cores), orcDaSolicitacao(solId, {soCaixas}), orcDevCarregar/ORC_DEV_PROPOSTAS (/api/desenvolvimento/propostas), orcPuxarDoDesenvolvimento/orcDevEscolher/orcDevPuxar, orcDevSolicitacaoDe/orcDevGarantirSolicitacao (a ponte sol_dev_<proposta>, o mesmo id da API), orcDevEsperandoLinhas, orcDevNaoPrecisa. js/34: devRotuloEsperaPreco. sistema.html: botão + modal-orc-do-dev. Teste: node tests/puxar-do-desenvolvimento.test.mjs (31, com mutações); o orcamento-da-amostra-chapa passou a carregar o orcItemDaCaixaSolic (§9.13: seguir as duas pontas).
v2.37.937
📐
A faca exportada ganha "ENTRADA DE MÁQUINA" na borda de baixo (sempre a parte de baixo) e os rótulos POSE 1, POSE 2… dentro de cada pose — em PDF, EPS e DXF.
Pedido do dono em
27/09/2026, olhando o preview da 04 FLOPS 70:
"quero que o arquivo saia dessa forma; tenho de definir também entrada de máquina, e que sempre a parte de baixo" ·
"deixa a entrada de máquina no arquivo quando exportar". Preview aprovado:
claude.ai/artifact/T6cPXwsngzotZWcAZk9VK1.
✅
Entrada de máquina: o dizer centrado na margem de baixo e quatro setas subindo pra dentro da faca (a borda que entra primeiro). É sempre a borda de baixo do desenho, sem campo pra escolher. No PDF e no EPS vai na camada COTAS (fica no arquivo; o designer só apaga se apagar as cotas); no DXF vai na Annotation, pra nunca virar linha de corte na facaria.
✅
POSE 1, POSE 2… escritos no centro de cada pose, na mesma camada. Pose 1 = a de baixo, à esquerda (a que veste o 3D). Faca de uma pose só não ganha rótulo.
🔒
Não muda: as linhas da faca, as cotas, o sentido da onda, o nome do arquivo, o 3D, a maleta pelas medidas (ganha só a entrada de máquina).
🔧 Por dentro: js/106-faca-eps.js — rotulosDasPoses(faca) (centro de cada pose pela mesma ordem do facaComPoses), o dizer e as setas nos três escritores (EPS: entrada + posesEps; PDF: setasEnt antes do BT e os textos na camada COTAS; DXF: Annotation). Teste tests/faca-do-dxf-com-poses.test.mjs agora com 116 checagens e 14 mutações acusadas (a entrada some / sobe pro topo, no PDF e no EPS; POSE escrita em faca de uma pose). faca-em-eps 91 e faca-em-dxf 51 seguem verdes. Sem servidor, sem Luan.
v2.37.936
🗄️
O npm run db:migrate passa a dizer em qual banco está, o que rodou, ONDE parou e o que ficou — a prova que o Luan manda de volta.
📌
O que estava acontecendo: em 25/09 o Luan rodou o migrate e a tabela do chat (migration 050) não apareceu no banco que a API usa (
grupomahnat): a API continua respondendo do blob antigo, e ela reconfere a cada 60 s. O script antigo parava no primeiro arquivo com erro e imprimia só "✗ Erro: mensagem" — sem dizer o banco e o usuário da conexão, sem dizer QUAL arquivo quebrou e sem conferir nada no fim. Localmente os 50 arquivos rodam limpos duas vezes seguidas (Postgres em Docker), então a falha é do ambiente do servidor, e o script tinha que conseguir contar qual.
✅
Agora o migrate imprime: host, banco e usuário antes de começar; um ✓ por arquivo; no erro, o nome do arquivo, o código do Postgres, a mensagem e quantos arquivos ficaram sem rodar (sai com código 1); e no fim a conferência —
chat_mensagem e
arquivos_upload existem? — mais as últimas versões registradas em
schema_migrations. A conexão também pode vir de variáveis de ambiente (DB_HOST…), que é como o teste roda sem tocar no
.env.
🔒
Não muda: nenhum arquivo de migration, nenhuma tabela, nada nas telas. Só o script e o que ele imprime.
🧰
Luan: depois do
git pull,
npm run db:migrate 2>&1 | tee /tmp/migrate.txt e mandar o arquivo. Se a primeira linha disser outro banco que não o
grupomahnat, é o
.env da pasta errada; se aparecer "✗ arquivo", é ali que trava. Depois
pm2 restart all (a API liga o chat sozinha quando a tabela aparece, mas as artes no banco só entram no restart).
🔧 Por dentro: scripts/migrate-schema.mjs reescrito (conexão .env + ambiente, ✓/✗ por arquivo, conferência final, JP_MIGRATIONS_DIR só pra teste). Teste novo tests/migrate-schema-diz-onde-parou.test.mjs (10 checagens num Postgres 16 em Docker: banco limpo, segunda rodada e um arquivo quebrado de propósito; sem Docker ele avisa que PULOU). Sem migration.
v2.37.935
🎨
AS CORES DO ORÇAMENTO VOLTARAM PRO ARQUIVO DE CORES — e a tela não mudou nada.
Duas versões de 20/09 escreveram cor à mão dentro do Editar Orçamento: a v2.37.883 (a caixinha "palete fora do padrão" e o fundo escuro das três vistas do palete) e a v2.37.899 (o botão verde-água "📐 Faca (PDF)"). A regra da casa, desde a v2.37.676, é que toda cor mora num lugar só (
css/00-tokens.css), senão trocar uma cor vira caça ao tesouro. O teste que guarda isso estava vermelho desde então.
✅ As 7 cores agora são lidas do arquivo, com
os mesmos valores de antes. Conferido no navegador, com o CSS real: as 7 saem idênticas, antes e depois.
✅ O fundo escuro dos desenhos ganhou nome próprio:
--desenho-fundo. Os desenhos de palete, de carga e da faca usam esse mesmo tom em uns 20 lugares, que continuam escritos à mão — dá pra passar pro nome novo quando quiser, sem mudar nada na tela.
🔒 Não muda: nenhuma cor, nenhum número, nenhum botão. Sem servidor, sem Luan.
🔧 Por dentro: --color-slate-975 (primitiva, #0a0e13) e --desenho-fundo (o papel) no css/00-tokens.css; no modal, var(--brand), var(--desenho-fundo), var(--teal-text) e rgba(var(--teal-dark-rgb),…). tests/orcamento-cores-do-arquivo.test.mjs voltou ao verde.
v2.37.934
🗄️
O BACKUP DO BANCO APARECE NA TELA, ONDE VOCÊ OLHA.
O único backup que protege de verdade é o do Mac (o
scripts/backup-banco.sh, todo dia às 12:30). Ele falhou
todo dia de 19/08 a 27/09 (
"DB_PASSWORD está vazio") e ninguém viu: o aviso morava numa notificação do Mac e num arquivo de log. A retenção de 14 dias apagou o último backup bom e
não sobrou nenhum.
✅
O script agora conta pro servidor cada resultado: o backup bom (quando, tamanho, onde ficou guardado) e a falha (quando e o motivo). Com o servidor fora do ar o backup sai igual — o aviso nunca atrapalha o backup.
✅
O 💾 Backup & Restauração ganhou um bloco no alto: vermelho
"SEM BACKUP DO BANCO HÁ N DIAS" (ou
"NENHUM BACKUP DO BANCO REGISTRADO") quando o último backup bom tem mais de 2 dias; verde com a data e o tamanho quando está em dia; cinza quando o servidor não respondeu — aí ele não diz nem que está em dia nem que está atrasado.
✅
Pontinho vermelho no ☁️ Backup do topo no mesmo caso. Ele se confere sozinho de meia em meia hora.
⚠️
Vai aparecer VERMELHO logo de cara, e é verdade: o servidor nunca recebeu aviso de um backup bom. Fica verde no primeiro backup que der certo depois que a senha nova do banco estiver no
.env do Mac.
⚠️
O agendamento das 12:30 roda o script da pasta PRINCIPAL do repositório no Mac. O aviso só começa quando aquela pasta estiver nesta versão — e isso não depende do servidor da fábrica voltar a puxar a main.
🔒
Não muda: o "Status atual" do mesmo modal (o arquivo do navegador), o backup manual, o cofre na nuvem e o selo "!" antigo, que segue desligado desde a v750. Sem rota nova, sem migration, sem Luan.
🔧 Por dentro: js/113-backup-banco.js (uma régua só pro bloco e pro pontinho), avisar_servidor no scripts/backup-banco.sh (grava o doc backup_banco pelo /merge, com o token do js/api-config.js publicado — o mesmo caminho do anexar-arte-caixa.mjs) e o gancho no abrirModalBackup (js/01). tests/backup-banco-na-tela.test.mjs: 40 checagens — inclusive o script de verdade no /bin/bash do macOS contra um servidor de mentira local — e 12 mutações acusadas. Era pra ser a 933: outra frente já tinha a 933 pronta num branch.
v2.37.932
📦
AS QUATRO MELHORIAS DE 20/09 QUE NUNCA TINHAM SIDO PUBLICADAS.
Pedidas pelo dono em
20/09/2026, marcadas na época como
"pronto e testado, ainda não publicado", e esquecidas no checkout principal quando a v2.37.923 publicou só a parte da faca. Achadas no diagnóstico de 27/09 e aprovadas de novo (
"pode fazer as quatro").
✅
A especificação do papel é a da CHAPA (
"isso começa no orçamento e o cadastro da caixa já puxa direto"). O bloco "📋 O que o cliente pediu" saiu da tela da caixa — era o mesmo número em dois lugares — e o Plano de Desenvolvimento imprime gramatura total, coluna, esmagamento e espessura da chapa cadastrada; campo que a chapa não tem sai "não cadastrado".
Nenhum dado apagado: o que estava guardado nesses campos continua na caixa (o salvar preserva).
✅
O palete do plano parou de sair vazio: procura a paletização por três caminhos (o salvo, o cadastro da caixa, a conta pela medida) antes de escrever "não cadastrado".
✅
3D: a dobra é suavizada em vez de parecer corte (
"nas dobras está cortada; tem que ser suavizada"), o painel escolhido acende (
"eu tenho que saber qual linha está selecionada") e o giro para enquanto se escolhe (
"o modo giratório tem que estar desligado pra isso").
✅
Arte que não serve pra esta faca estica na faca inteira (
"o desenho não está na caixa toda"): se o arquivo não cobre nem metade do lado maior do blank (uma folha A4 anexada por engano), vale a reserva de sempre, com a marca "esticada". A mesma régua no orçamento e no 3D.
⚠️
Achado na conferência da tela real, e consertado junto: a remoção do bloco no commit de 20/09 tirava a abertura dele e deixava o fechamento — sobrava um
</div> que jogava o
rodapé da janela da caixa (o botão "Salvar Caixa") pra fora da janela. Os testes da época não olhavam a estrutura; agora
tests/janela-da-caixa-inteira.test.mjs acusa.
🔒
Não muda: a faca do ArtiosCAD que já está no ar (v2.37.923), preço, peso e produção. Sem servidor e sem migration.
🔧 Por dentro: porte do commit 2a8746e0 (só js/08, js/70, js/101, js/104; o resto do commit era número de versão). Um conflito no js/101: ficou a régua nova jpArteMedidaServe e a assinatura arteCalibracao3D(…, opts) que a main ganhou na v923. Testes: espec-vem-da-chapa (35), plano-desenvolvimento-fiacao (89), caixa3d-camera-e-papel (13/13 mutações), arte-na-faca-orcamento (14/14) e os 4 da faca. Preview aprovado: claude.ai/artifact/PcLDt2B7UNHP1MVLnRTxTt
v2.37.931
⏳
CARTÕES "AGUARDANDO PREÇO" × "PREÇO APROVADO" NO ORÇAMENTOS — aprovar já manda pro vendedor, e a caixa que já é pedido não duplica.
Pedidos do dono em
27/09/2026:
"no desenvolvimento não tem como colocar preço, e no orçamento não tem esse 45 — teria que aparecer pro PCP fazer o preço e validar pro vendedor" ·
"por que esse aviso 'não achei' se está aí dentro do orçamento?" ·
"vamos criar um cartão com aguardando preço e com preço aprovado" ·
"puxar um por vez, somente o que está em espera". Preview aprovado:
cartões.
📌
O que estava acontecendo (conferido no dado real): (1) o
0045 PAPELARIA REVAL e o
0047 TANGARA, do Desenvolvimento, foram marcados "✅ atendida" na fila 📨 em 20/09 às 11:49
sem ter orçamento — e tudo que está "atendida" some; (2) o
0046 TANGARA foi aprovado, mas salvo pelo "💾 Salvar" e não pelo "📨 Salvar e enviar": o app do Armando ficou em "Aguardando PCP"; (3) no
0017 REVAL, um computador ainda com a versão antiga gerou o pedido da TAMPA com
60.000 um minuto antes do ajuste pra 25.000 chegar — o sistema novo, certo, não mexeu no pedido, mas o aviso dizia "não achei" e "os números já estão com o ajuste" (os dois errados); depois, editar a TAMPA no orçamento apagou a marca "já virou pedido" e o botão "Gerar caixas + pedidos" passou a oferecer ela de novo.
✅
Comercial → Orçamentos · dois cartões entre os números do alto e a lista:
⏳ Aguardando preço (Desenvolvimento e vendedores sem orçamento + orçamento com preço feito falta aprovar) e
✅ Preço aprovado (esperando o cliente, com o total e quantos não chegaram no vendedor / estão sem vendedor).
Tocar filtra a lista; tocar de novo mostra tudo. Substituem a faixa da v2.37.921.
✅
Um por vez, só o que está em espera: cada proposta é uma linha com o seu
💰 Dar preço (puxa só ela pra um orçamento novo, com caixas, medidas, cores, vendedor e o mesmo número). "Atendida"
sem orçamento não esconde mais — o 0045 e o 0047 voltam, com o aviso "marcada atendida em 20/09 sem orçamento". Pra tirar da lista de verdade:
✕ não precisa de preço (não apaga nada).
✅
"✓ Aprovar preço" já manda o preço pro app do vendedor (cria o recorte que faltava), mesmo salvo pelo "💾 Salvar". No ✅, cada orçamento diz
📱 fulano já vê,
⚠️ não chegou no fulano (com o botão
📨 Enviar pro vendedor) ou
sem vendedor.
✅
O aviso do ajuste diz a verdade: "⚠️ TAMPA REVAL já tinha virado pedido (60.000 cx · Programado · entrega 15/10) quando o ajuste chegou — o ajuste NÃO foi aplicado nela. Se o cliente quer 25.000, corrija o pedido na carteira." · e só diz "os números já estão com o ajuste" quando algo foi aplicado.
✅
Caixa que já é pedido não duplica: editar ela no orçamento mantém a marca (e avisa que mudar ali não muda o pedido), e o "Gerar caixas + pedidos" (e o aceite que vira pedido sozinho) reconhece pela carteira a caixa que já tem pedido deste orçamento, mesmo se a marca tiver sumido.
🔒
Não muda: os 4 números do alto, o Editar/Ver/Histórico, a fila 📨 Solicitações, quem faz e aprova o preço (o PCP), o preço voltando pro Desenvolvimento;
nenhum pedido é criado, mudado ou apagado — o da TAMPA (60.000) quem corrige é o PCP, na carteira. Sem banco, sem API, sem restart.
🔧 Por dentro: js/111 ganhou vendedorVe (a mesma conta do juntarMeusOrcamentos do app), resumoCartoes, ordenarAprovados, curarMarcaDePedido/pedidosDaCaixa (pedido ↔ caixa por orcamentoId + codigo; duas caixas de mesmo nome não são adivinhadas), aguardandoPreco sem esconder "atendida" (naoPrecisaPreco esconde) e aplicarNoOrcamento com jaPedido. js/08: orcCartoesHtml/ORC_FILTRO_CARTAO/orcFiltrarCartao, orcAguardandoPrecoLinhas, orcNaoPrecisaPreco, orcTarjaAjusteHtml (lê a carteira pro registro antigo), orcGarantirRecorteVendedor (no aprovarOrcamento, antes do espelho) + orcEnviarProVendedorAgora, orcManterMarcasDoItem no orcAdicionarItem, cura no orcParaPedido/orcParaPedidoConfirmar/orcAutoConverterDoAceite/renderOrcamentos. Testes: node tests/cartoes-orcamento.test.mjs (48, com mutações), tests/ajuste-vendedor.test.mjs (109); a régua do orcamento-manda-em-todos passou a ser "toda gravação do recorte passa pelo montador" (o aprovar virou a 2ª porta).
v2.37.930
🔒
OCORRÊNCIAS: O SERVIDOR PASSA A RECUSAR A LISTA INTEIRA + as dependências da API sem aviso de segurança.
Item 6 do plano do diagnóstico de
27/09/2026, aprovado pelo dono (
"pode fazer subir"). Desde a v2.37.565 as três telas (sistema, app do operador, app da Expedição) gravam
uma ocorrência por vez e a lista antiga ficou congelada — mas o servidor ainda aceitava que um aparelho com a tela velha em cache mandasse a lista inteira por cima. Foi assim que 5 ocorrências sumiram em agosto.
✅
Servidor: o documento
ocorrencias entrou na lista de "só por merge", junto do estoque, dos romaneios, das saídas de palete e do estado dos paletes. Gravar a lista inteira agora responde
409 e aponta pro caminho certo. As telas de hoje nunca fazem isso (conferido no código), então ninguém sente nada.
✅
Dependências da API: qs 6.15.2 → 6.16.0,
body-parser 1.20.5 → 1.20.8,
express 4.22.2 → 4.22.3 e
side-channel 1.1.0 → 1.1.1. Os 3 avisos de segurança (negação de serviço por parâmetro de URL montado de propósito) viraram
0. Só a trava de versões mudou; o
package.json é o mesmo.
🔒
Não muda: nenhuma tela, nenhum número. Registrar, editar e excluir (marcar) ocorrência seguem iguais nos 3 apps. Nenhum dado tocado, sem migration nova.
🧰
Luan, nesta ordem (vale também pra v2.37.929): (1) conferir que o
.env da API
não tem
API_DEV_TOOLS=true — com isso ligado a proteção da 929 fica desligada; (2)
cd api && npm ci; (3)
npm run db:migrate (idempotente: aplica 050/051 se faltarem); (4)
pm2 restart jp-cartonagem-api --update-env (nunca
all); (5)
pm2 logs jp-cartonagem-api --lines 50 sem "Cannot find package" e com
[rbac] sincronizado no boot; (6) um
DELETE /api/pedidos/tudo com o token tem que voltar
403 "desligado".
🔧 Por dentro: api/src/routes/snapshots.js (SO_MERGE += 'ocorrencias'), api/package-lock.json. Teste: node tests/ocorrencias-so-merge.test.mjs (8 checagens, 4 mutações acusadas); o contador de mutação desse teste e do apagar-tudo-desligado passou a separar "alvo sumiu" de "acusada" (antes um alvo inexistente contava como acusado). Preview aprovado: claude.ai/artifact/U3Tm8ApMDpkKz9BzdwZH8f
v2.37.929
🔒
APAGAR A FÁBRICA INTEIRA FICOU DESLIGADO NO SERVIDOR (REGRA ZERO).
Do diagnóstico do sistema inteiro de
27/09/2026, aprovado pelo dono (
"vamos arrumar" ·
"pode fazer"). Três rotas apagavam tudo — a carteira com a produção em cascata (
DELETE /api/pedidos/tudo), toda a produção que veio dos apps (
DELETE /api/registros/operador/limpar) e qualquer documento fora dos 4 protegidos (
DELETE /api/snapshots/:chave: cargas, escalas, ocorrências, config, manutenções, ordens de compra) — e o servidor só conferia o token da API, que é o mesmo em todo aparelho e mora num arquivo que qualquer um baixa. A tela pedia admin original e duas confirmações, mas isso vive no navegador.
✅
Servidor: as três rotas passam por um guarda novo. Na fábrica respondem
403 "Apagar tudo está desligado neste servidor (REGRA ZERO)" sem tocar no banco, e a tentativa fica no
audit_log. Só passam em ambiente de teste (
API_DEV_TOOLS=true no .env da API) e, mesmo lá, só com o crachá do admin original.
✅
Importação de relatório: saiu a reserva escondida que, num 404 da rota
/replace, apagava a carteira inteira no servidor e reenviava a lista do PC. Agora a importação para e diz
"o servidor não aceitou a importação; nada foi apagado nem enviado".
✅
Os dois botões dizem a verdade: 💾 Backup → 🧹 Resetar sistema → ☁️ Limpar servidor também e
📋 Cadastros → 🗑️ Limpar dados leem o 403 e avisam
"desligado no servidor, nada foi apagado" — antes engoliam a resposta, apagavam o navegador e diziam "✓ apagados" mesmo com o servidor tendo recusado ou a rede caído. O marcador que manda os outros PCs descartarem a lista local só sai se a tabela foi apagada de verdade.
🔒
Não muda: excluir um pedido (lápide e 🗑️ Lixeira), anular registro, o ✕ do estoque, "🗑️ Limpar este navegador" e a importação normal seguem iguais. Nenhum dado foi tocado. Até o Luan reiniciar a API o servidor segue como estava; a tela já sobe sem quebrar nada.
🧰
Luan: pm2 restart jp-cartonagem-api --update-env. Sem migration.
🔧 Por dentro: api/src/middleware/apagar-tudo.js (novo: apagarTudoDesligado + guardaApagarTudo), routes/pedidos.js, routes/registros.js, routes/snapshots.js; js/02 substituirPedidosNoServidor sem a reserva; js/01 resetarServidorDeTestes + jpApagarTudoDesligado; js/08 executarLimpeza + _limpezaDesligada. Teste: node tests/apagar-tudo-desligado.test.mjs (31 checagens, 8 mutações acusadas). Preview aprovado: claude.ai/artifact/UpWYjCu5pEhT8JH4nmcpSp
v2.37.928
🚨
NENHUM MODAL ABRIA — Editar, Ver/Enviar, Histórico, tudo mudo — desde a v2.37.920 (24/09, 14:00).
O dono,
24/09/2026:
"não consigo abrir nada no orçamento, nem editar nem ver e enviar, histórico, nada" ·
"nenhum botão funciona na página de orçamento" ·
"em todos os computadores logados" ·
"no dia 23/09 estava tudo normal".
📌
O que estava acontecendo: a entrada da v2.37.920 no histórico de versões abria dois
<div> (o cartão e o texto) e não fechava nenhum. O navegador então engoliu tudo que vinha depois —
os 58 modais do sistema — pra dentro da janela do histórico, que fica escondida. Os botões funcionavam, o modal "abria" (a classe entrava), mas dentro de uma janela invisível: tamanho zero, ninguém vê. Não era cache, não era dado, não era o app do vendedor: era HTML. Achado olhando o navegador do dono: o pai do
#modal-orcamento era o
#modal-changelog.
✅
Os dois fechamentos de div entraram na entrada 920. Todo modal voltou a ser filho direto do
body (conferido com parser e no navegador).
✅
Teste que impede de voltar: tests/modais-filhos-do-body.test.mjs lê o sistema.html com um parser e acusa (1) qualquer
.modal-bg que não seja filho direto do body e (2) qualquer entrada do histórico com div aberto sem fechar — é o que a régua do §13.3b (conflito de changelog) não pegava.
✅
⚠️ Erro na tela: toda exceção de programa (ReferenceError, TypeError, "before initialization", arquivo que não carregou) vira uma faixa vermelha no alto com arquivo:linha — o print que resolve. Erro de rede não entra.
sistema.html?diagnostico=1 mostra o quadro completo (versão, navegador, sentinelas, tentativas da cura, últimos erros, teste do Editar).
🔒
Não muda: nada de dado, banco ou API — sem migration, sem restart. As v925/926 (cura do boot) ficam: elas resolvem outro caso (arquivo pela metade) e não este.
🔧 Por dentro: sistema.html (entrada 920 fechada; bloco ⚠️ erro na tela junto da 🩹 cura). Testes: node tests/modais-filhos-do-body.test.mjs, tests/cura-do-boot.test.mjs (27). Lição: changelog é HTML dentro de um modal — div aberto ali esconde o sistema inteiro, e o conflito de merge do §13.3b é o jeito mais fácil de perder um fechamento.
v2.37.927
🏷️
CAIXA RENOMEADA CONTINUA SENDO ACHADA NO TABLET.
Pedido do dono em
25/09/2026, com o print do tablet:
"por que essas imagens se está tudo certo! eu quero que volte a aparecer como estava! quando fala que não está no PC isso significa o quê" (TANGARA · pedido 24110, "Caixa ainda não está no PC").
📌
O que aconteceu, conferido no servidor: a caixa foi renomeada duas vezes no dia (10:57 "CX 17 AGUA SANITAIRA UNI 6x2" → "17 AGUA SANITAIRA UNI 6x2"; 13:47 → "17 AGUA SANITARIA UNI 6x2"). No servidor o pedido já estava com o nome novo e ligado à caixa; o tablet ainda carregava a cópia antiga do pedido (nome velho, sem vínculo). O nome não batia mais e, pelo número (17, 6, 2), ficava ambíguo com a "06 AGUA SANITARIA", então o app não arriscou.
"Caixa ainda não está no PC" significa só isso: o app não achou, entre as caixas carregadas, uma que case com o pedido que ele tem na mão.
✅
Agora: o app do operador também reconhece os
nomes anteriores da caixa (o cadastro guarda até 20 a cada renomeação). O pedido com o nome velho acha a caixa na hora, mesmo antes de sincronizar. Continua valendo: só dentro do mesmo cliente, depois do nome atual e antes de qualquer chute por começo de nome ou número; na dúvida, "não está no PC" em vez de chutar.
🔒
Não muda: nenhum pedido ou caixa é alterado; os outros passos da busca (vínculo, nome, começo, número) ficam iguais. Sair do pedido e entrar de novo no tablet continua puxando o pedido atualizado com o vínculo.
🔧 Por dentro: painel_operador.html (buscarCaixaCadastrada, passo 2b: codigosAnteriores). Teste: tests/caixa-renomeada-nome-anterior.test.mjs (com mutação). Preview aprovado: claude.ai/artifact/Nt5xJYtLcqzFCJiW8JsT5L
v2.37.926
🩹
A CURA DO BOOT TAMBÉM OLHA O CSS — e aceite atrasado do app não vira pedido sozinho.
O dono,
24/09/2026, depois da v925:
"nenhum botão funciona na página de orçamento" — a lista desenhava, mas Editar, Ver/Enviar e Histórico não faziam nada.
📌
O que estava acontecendo: quando é a
folha de estilo (css/main.css, 66 KB) que veio pela metade, os botões funcionam e os modais abrem — mas a regra que MOSTRA o modal não chegou, então ninguém vê nada. A cura da v925 só conferia os arquivos de JavaScript.
✅
Sentinela no fim de cada CSS (
css/main.css e
css/00-tokens.css): a última regra deixa uma marca; sem ela, a cura refaz os downloads furando o cache e recarrega — o mesmo caminho da v925, agora pra CSS também. E as duas folhas ganharam endereço novo nesta versão (todo mundo baixa fresco).
✅
Aceite antigo não vira pedido sozinho: desde a v921 o "🤝 Cliente aprovou" do card "montado pelo PCP" chega no sistema — inclusive os de semanas atrás, que o PCP já pode ter tratado na mão. Aceite com mais de 7 dias entra como aceito, mas fica pro botão "Gerar caixas + pedidos", com aviso no cartão. Aceite fresco segue virando pedido sozinho.
🔒
Não muda: login, orçamentos, banco, API — sem migration, sem restart.
🔧 Por dentro: bloco 🩹 CURA DO BOOT lê getComputedStyle(documentElement).getPropertyValue('--jp-css-main-fim') / --jp-css-tokens-fim; js/08 jpSincronizarAceites marca o.aceite.antigo (> 7 dias) e não põe em paraConverter. Testes: tests/cura-do-boot.test.mjs (20) e tests/ajuste-vendedor.test.mjs (108).
v2.37.925
🩹
CURA DO BOOT — o sistema se conserta sozinho quando um arquivo veio pela metade.
O caso (dono,
24/09/2026, minutos depois da v2.37.921 subir):
"não consigo entrar" — a tela de login dizia
Cannot access 'JP_ESPREMIVEIS' before initialization — e depois
"não consigo abrir nada no orçamento, nem editar nem ver e enviar, histórico, nada".
📌
O que estava acontecendo: o servidor estava íntegro (js/01, 02, 07 e 88 conferidos byte a byte) e num navegador limpo tudo abria. O navegador do dono tinha guardado uma
cópia pela metade de um arquivo grande (o js/01 tem 780 KB): a atualização automática recarrega a página no meio dos downloads, e o pedaço entra no cache HTTP (1 h) ou no do service worker e é servido quebrado a cada F5. As funções existem, mas todo
let/const depois do corte fica "antes da inicialização" — o login estoura ao gravar a sessão e a aba Orçamentos não abre nada.
✅
Ao terminar de carregar, o sistema confere se cada arquivo de boot chegou até o fim (o último
let/const do js/01, js/02, js/07, js/08, js/09, js/48 e as funções do login e do orçamento). Se algum falhou, refaz o download de todo js/css
furando o cache, apaga o cache do service worker, desregistra ele e recarrega na mesma tela. No máximo 3× por aba (não entra em loop) e
sem tocar nos dados locais (fila de coisa não enviada fica). Manual:
sistema.html?curar=1.
🔒
Não muda: nada no login, nos orçamentos, no banco ou na API — só o fim do sistema.html. Sem migration, sem restart.
🔧 Por dentro: bloco inline 🩹 CURA DO BOOT no fim do sistema.html (sentinelas ADM_APPS, reproPollInterval, _lnkEsq, MIC_VALOR_MANUAL, CPR_ACESSO_BADGE, JPNotaOrc; fetch(url, {cache:'reload'}) em todo ?v=; contador em sessionStorage jp_cura_boot_tentativas). Teste: node tests/cura-do-boot.test.mjs (16 checagens, 2 mutações). Conferido na página real: boot saudável fica quieto; ?curar=1 refaz e recarrega.
v2.37.924
🔔
CHAT — A MENSAGEM CHEGA NA BANDEJA DO CELULAR, IGUAL WHATSAPP, COM O APP FECHADO.
Pedido do dono em
22/09/2026:
"quero que a notificação fique igual o WhatsApp, que aparece em notificação". Até aqui o chat só apitava com a tela aberta: operador com o celular no bolso e o PCP em outra aba não ficavam sabendo.
✅
Botão 🔔 Ativar notificações — na lista de operadores do Chat (PCP) e no cabeçalho do chat do app do operador. Uma vez ligado no aparelho, toda mensagem chega na bandeja com
quem mandou e o texto: "💬 Miller · Máq. B Slotter — Acabou a chapa do 31644". Máquina parada chega como
"🔴 Grampeadeira parou", vibra mais e fica na bandeja até alguém ver.
Tocar abre direto na conversa.
✅
Igual WhatsApp de verdade: com o app na frente a bandeja não aparece (só o bip e a mensagem na tela); a mesma conversa substitui o aviso anterior em vez de empilhar 30; o PCP recebe de todos os operadores, e cada operador só recebe o que é dele.
✅
O app do operador passou a mandar pelo servidor (POST com trava) em vez de reescrever a lista inteira do celular — dois operadores falando ao mesmo tempo não se apagam mais. O caminho antigo ficou de reserva.
✅
Ligou uma vez, fica ligado: a cada versão nova o app se atualiza
desregistrando o service worker — e a inscrição da notificação morre junto com ele. O aparelho se re-inscreve
sozinho na abertura seguinte, sem pop-up e sem o operador saber. Sem isso a notificação parava calada a cada atualização (quase todo dia) e só voltava se alguém reparasse no botão amarelo.
📱
Limites que são do aparelho, não do sistema: no iPhone só notifica com o app
instalado na tela inicial (Compartilhar → Adicionar à Tela de Início) — o botão explica isso na hora. No Android e no PC funciona no navegador mesmo.
🔧
Pro servidor (Luan, uma vez): cd api && npm i web-push && npx web-push generate-vapid-keys, colar
VAPID_PUBLIC/
VAPID_PRIVATE no
.env e
pm2 restart. Sem isso o chat segue exatamente como era (o botão avisa "servidor sem push") — nada quebra.
🔧 Por dentro: api/src/lib/chat-push.js (Web Push/VAPID; inscrições no snapshot chat_push_subs por merge; destinatarios decide quem recebe pelo de da mensagem; endpoint morto sai sozinho; sem chave = no-op), rotas /api/chat/push/{chave,inscrever,remover,estado,testar} em routes/chat.js e o gancho no POST /mensagens (depois do res.json, com catch), sw.js (eventos push e notificationclick; app na frente → postMessage em vez de bandeja), js/112-chat-push.js (permissão, inscrição, re-inscrição silenciosa quando o auto-update leva o SW, botão com estado, iPhone), ganchos em js/09 e no painel_operador.html. As inscrições gravam em transação (BEGIN → FOR UPDATE → COMMIT, igual o /merge da casa) e erro de leitura aborta em vez de gravar por cima da lista. Teste: tests/chat-push-igual-whatsapp.test.mjs (43 regras).
v2.37.923
📐
A FACA SAI IGUAL AO DXF — com as poses do cadastro e as cotas — em PDF, EPS e DXF; o 3D veste só uma pose; a ficha da clicheria e da facaria diz a faca inteira.
Pedido do dono em
24/09/2026, com o EPS da
TANGARA 04 FLOPS 70 (335 × 245 × 245, DXF "CX FLOP'S 1x1 Com chanfro", 2 poses) na mão:
"quando eu coloco exportar EPS ele vem diferente. O correto é vir igual [ao DXF] pra colocar no Illustrator e devolver a arte, o sistema põe em 3D e depois manda pra clicheria. Essa caixa tem pose 2: quando exportar tem que exportar assim, no 3D tem que valer só uma, e pra clicheria tem que valer 2, que é como a faca vai ser feita. E a faca também tem que sair com DXF e com as cotas. O leque marca como ignorar: o leque é sentido de onda, tem que ter na horizontal e na vertical. O que for feito aqui vai servir pra todas as outras." Preview aprovado:
claude.ai/artifact/T6cPXwsngzotZWcAZk9VK1.
📌
O que estava acontecendo: o exportador pedia a geometria da caixa e, quando a faca era um DXF, ela chegava como "texto pra ler depois" (assíncrono). O exportador não esperava e caía na
fórmula da maleta — saía a caixa genérica pelas medidas: abas retas sem o chanfro de 50 mm, aba de cola em trapézio de 30, rasgos de 8,
1 pose de 1.198 × 499 numa faca real de
1.207 × 501. No orçamento, o item com DXF nem saía ("Não consegui montar a faca deste item"). E a ficha da clicheria dizia "Medida da chapa: 1207 × 501" — o molde de UMA pose — quando a faca vai ser feita com duas.
✅
Cadastros › Caixas › rodapé da janela · 📐 Faca (PDF) · EPS · DXF: a faca sai das
linhas do DXF, do jeito que você classificou no 🔪 Linhas da faca (corte, vinco e
picote — que sai sempre; o "destacar o picote" é só do 3D; linha marcada
Ignorar some de tudo). Repetida nas
poses do painel Corte e Vinco (poses no comprimento × na largura, espaço, encaixe com sobreposição e deslocamento — o mesmo arranjo que a tela desenha; pose 1 = a de baixo, à esquerda). Na 04 FLOPS 70: 2 poses empilhadas,
1.207 × 1.002. Prancheta = a faca inteira + folga; camadas FACA / COTAS / ARTE como antes; o TrimBox marca a faca inteira.
✅
As cotas, medidas pelos vincos do DXF: painéis entre os vincos verticais (337 · 249 · 339 · 247 · cola 35), abas e corpo entre os horizontais (125 · 251 · 125), 1 pose (501) e a faca inteira (1.207 × 1.002) — com
régua e seta, na camada COTAS (apagável de uma vez). O cabeçalho diz caixa, cliente, medida interna, onda, poses, faca e chapa (1.237 × 1.032, refile 30). O nome do arquivo ganhou as poses:
FACA 04 FLOPS 70 335x245x245 2 poses v1.pdf.
✅
Sentido da onda: campo novo no painel Corte e Vinco do cadastro (
⫵ Vertical, padrão, ou
≋ Horizontal) — vai escrito e desenhado nos três arquivos (no DXF, na camada Annotation, pra nunca virar painel). O "leque" que o designer deixa no DXF é isso: marca como Ignorar no 🔪 e o sistema escreve o dele.
✅
DXF pra facaria (botão novo): as mesmas linhas e poses, camadas
Design (corte cor 1 · vinco cor 2 · picote cor 3) e
Annotation (cotas, cor 20; sentido da onda; entrada de máquina), no padrão do ArtiosCAD — e o nosso leitor lê de volta. Junto veio a maleta conferida contra o ArtiosCAD (aba de cola de 35 com chanfro de 6, ponta do rasgo em semicírculo) e o arco que sumia do EPS (v2.37.908, que estava num branch sem subir).
✅
A arte que volta (6.5 Arte / item do orçamento) é conferida contra a faca inteira: "✅ arte encaixada na faca (1.207 × 1.002 mm)".
🧊 3D: a caixa continua sendo uma pose; quando a arte vem na faca inteira, só a
pose 1 veste a caixa (antes ela cairia centrada: metade de cada pose no painel).
✅
Orçamento › item com Corte e Vinco › 📐 Faca: mesma regra (as poses do projeto) — e o item com DXF voltou a exportar.
✅
Desenvolvimento › ficha › 🖨️ Enviar arte pra clicheria / 🔪 Encomendar faca: a ficha ganha
"Faca: 1207 × 1002 mm · 2 poses (1 × 2)" e a chapa de verdade (1237 × 1032); o link diz "Arquivo (PDF · 2 poses)".
🧰 Luan: pm2 restart (sem migration) — até lá a ficha segue como era.
🔒
Não muda: o 🔪 Linhas da faca, o motor do 3D e as dobras/base que você ajusta, o Plano de desenvolvimento, o desenho do painel Corte e Vinco, as "poses por chapa" da produção (1 chapa = 2 caixas), a programação; nenhum arquivo já anexado (arte, DXF, clichê) é trocado sozinho. Caixa
sem DXF continua saindo pela maleta das medidas. Se o painel Corte e Vinco está 1 × 1 mas "poses por chapa" diz 2, sai 1 pose e avisa — o sistema não inventa arranjo. Caixa com DXF que não dá pra ler
não cai mais na fórmula: avisa e não exporta.
🔧 Por dentro: js/105 ganhou JPLinhasFaca.facaDaCaixa / entsParaFaca (picote = cor 3, ignorar fora); js/106: jpFacaDoDxf (segmentos → facaComPoses com o arranjo do cx.cv → cotasPelosVincos), jpFacaDaCaixa virou Promise (DXF > maleta; DXF ilegível = null), jpBaixarFaca/orcBaixarFaca assíncronos, cabeçalho e sentido da onda nos três escritores, réguas com seta no PDF/EPS, jpFacaEpsNome(cx, ext, faca); js/101: arteCalibracao3D(…, {facaTotal}) alinha a pose 1 pelo canto; js/08: botão DXF, cxArteEncaixeSync espera a faca, jpFacaTotalDaCaixa pro 3D da caixa e do plano; js/23: cx-cv-onda-dir → cv.ondaDir; API: facaInteiraDaCaixa em dadosDaFicha + linha "Faca" em lib/ficha-encomenda.js. Teste novo tests/faca-do-dxf-com-poses.test.mjs (99 checagens com a faca REAL da 04 FLOPS 70, 10 mutações acusadas); faca-em-eps 91 e faca-em-dxf 51 verdes.
v2.37.922
🚛 CARGA CONCLUÍDA NÃO SOME MAIS DA LISTA — e as duas cargas de 23/09 voltaram.
Pedido do dono em 24/09/2026: "tem um romaneio que sumiu! e o da tangara do dia 22" — "o empilhadeirista falou que mandou e bipou os paletes mas não está aqui".
📌 O que estava acontecendo: não era o romaneio. Em 23/09, entre 11:25 e 23:39, um aparelho gravou a lista de cargas inteira por cima do servidor com uma cópia de antes das 08:29 — e as DUAS cargas fechadas naquela manhã pelo João Issac (ACH9A34 08:29 · TCHETTO + TANGARA, romaneios Nº 104/105; EJY-5745 11:25 · FORTYS + TANGARA, Nº 106/107) sumiram do Histórico. Os 4 romaneios e as saídas de palete continuaram no servidor, intactos. A lista cargas é gravada inteira por 8 lugares (app da Expedição ×4, sistema ×4): quem grava por último ganha — a mesma família dos 6 romaneios de 21/08.
✅ Servidor (routes/snapshots.js + lib/cargas-protecao.js): antes de gravar, compara a lista que chegou com a do banco e DEVOLVE toda carga concluída que sumiu — nas 3 portas (PUT, /sync e /merge), com registro no log de qual carga e quem mandou. É a mesma trava da lista do operador (v2.37.746). Carga aberta segue como hoje (ela vive no livro de bips).
✅ App da Expedição: na hora de finalizar, se a leitura da lista falhar, a carga NÃO fecha com a lista local do celular (era a porta mais provável): avisa e pede pra tocar em Finalizar de novo. Nada se perde — a bipagem fica no rascunho e no livro.
✅ Sistema (js/08): a segunda cópia da lista de cargas (Cadastros) virou só leitura — quem grava é a Expedição (js/10).
✅ As duas cargas foram restauradas no servidor (96 → 98 cargas), reconstruídas dos romaneios e das saídas de palete, com a marca de restauração dentro do registro (REGRA ZERO: fica o rastro).
🧰 Luan: pm2 restart pra parte do servidor valer (sem migration). Até lá valem só as partes do app e do sistema.
v2.37.921
🎨
A ARTE ENTRA PELO APP DO VENDEDOR, ✏️ ele AJUSTA a quantidade sem devolver pro PCP, e 🧪 o Desenvolvimento aparece na aba Orçamentos.
Pedidos do dono em
24/09/2026:
"quero que ele possa colocar a arte no orçamento e também editar" ·
"ele pode trocar a quantidade, menos o valor; se ele mexer no valor tem um aviso que será descontado da comissão" ·
"quantidade abaixo pode, mas com aviso do kg cadastrado" ·
"no desenvolvimento tem um orçamento mas na aba do orçamento não tem o desenvolvimento… o vendedor acompanha tudo e quantas revisões" ·
"pode ser PDF, arquivo AI ou qualquer tipo de arquivo". Preview aprovado:
ANTES × DEPOIS.
📌
O que estava acontecendo: a única imagem que o vendedor mandava era a foto do modelo (só no corte e vinco) — a arte ficava no WhatsApp dele e o PCP anexava depois; no card já orçado ("montado pelo PCP") não tinha como mudar a quantidade sem o PCP refazer; a amostra do Desenvolvimento só aparecia na fila 📨, não na aba onde o comercial trabalha; e o vendedor não via em que etapa o negócio estava nem quantas revisões já tinha.
Achado no caminho: o card "montado pelo PCP" não carregava o elo com o orçamento (
orcamentoId) e o sincronizador do sistema IGNORAVA o "🤝 Cliente aprovou" desses cards — o aceite morria no doc das solicitações.
✅
App do Vendedor · solicitação: bloco
🎨 Arte da caixa em toda caixa (maleta e corte e vinco),
qualquer arquivo (PDF, AI, CDR, imagem…), até 15 MB; no computador cola (Ctrl+V) ou arrasta. Trocar vira v2, a anterior fica guardada. Reeditar não perde a arte.
✅
App do Vendedor · card orçado: botão
✏️ Ajustar (enquanto não virou pedido).
Quantidade muda à vontade — a linha e o total recalculam com o preço do PCP (Nº 0017 REVAL: 60.000 → 50.000 cx = R$ 53.498,90; total R$ 144.000,83 → R$ 133.301,05); abaixo do
kg mínimo da chapa avisa em amarelo, não barra.
Preço fica com 🔒: destravou e baixou → aviso vermelho com a conta (R$ 1,070 → R$ 1,000 em 50.000 cx =
R$ 3.498,90 saem da comissão) e o Salvar só libera depois de marcar "Estou ciente"; acima do PCP pode, sem aviso.
Arte por caixa: anexar ou trocar (vira versão nova). O app já mostra o número novo ("⏳ enviado ao PCP") e, quando o sistema aplica, "✔ aplicado no PCP".
✅
App do Vendedor · acompanhar: rev N ao lado do cliente (o mesmo número que o PCP vê) e a
trilha em todo card — 🧪 Desenvolvimento › 💰 Preço › 🤝 Aceite › 🏭 Pedido — com a etapa atual em amarelo.
✅
Sistema · 💰 Orçamentos: faixa
⏳ Aguardando preço no alto, com o que chegou do Desenvolvimento (primeiro) e dos vendedores e ainda não virou orçamento — botão
💰 Dar preço (o mesmo "Fazer orçamento" da fila 📨). O card precificado ganha o selo
🧪 do Desenvolvimento · ORC-NNNN. O ajuste do vendedor chega como
tarja ✏️ no card (igual à da revisão de preço), vira uma
revisão assinada pelo vendedor, e o aceite usa a quantidade ajustada.
✅
Sistema · 📨 Solicitações: a arte anexada pelo vendedor aparece no card (abre no navegador) e o "Fazer orçamento" já traz o item com ela — entra dentro da faca, no 3D e segue pra caixa/Desenvolvimento/clicheria como a arte que o PCP anexa.
✅
Aceite do card "montado pelo PCP" passa a chegar no orçamento (o card leva o
orcamentoId; o sincronizador também aceita o id do documento embrulhado).
🔒
Não muda: o preço unitário é do PCP (trocar a quantidade não recalcula preço); 🤝 Cliente aprovou, 💬 revisar preço, 👁️ Ver / Enviar, PDF e WhatsApp seguem iguais (só mostram a quantidade ajustada e a linha 🎨); o PCP continua liberando o preço e gerando os pedidos; caixa que já virou pedido fica travada; a conta da comissão (aba 💰 Comissão e relatório) não se altera sozinha — o desconto fica REGISTRADO no orçamento pro PCP aplicar; a fila 📨 continua e o preço continua voltando pro Desenvolvimento; nada no banco nem na API — sem migration, sem restart.
❗
Fora desta versão: o botão "💰 Fazer orçamento" que o dono viu travado no Nº 0062 TANGARA — a causa depende dos dados reais (com dados vazios o botão abre) e fica pra apuração com o sistema aberto.
🔧 Por dentro: arquivo novo js/111-ajuste-vendedor.js (JPAjuste: calcular, montarAjuste, aplicarNoOrcamento idempotente por em e casando índice+ref, trilha, aguardandoPreco, solicOrcamentoId, arquivoValido/nomeArquivo/trocarArte) — a MESMA régua nos dois lados. js/08: orcRecorteParaVendedor (+id, revisao, ajusteVendedor, item arte/chapaId/pesoMinKg), orcDaSolicitacao (item nasce com arte), jpSincronizarAceites (aplica s.ajusteVendedor ANTES do aceite via orcVersaoRegistrar + orcVendedorRefrescar; id por JPAjuste.solicOrcamentoId), orcAguardandoPrecoHtml/orcSolicDoOrcamento, tarja e selo no card, 🎨 no item. js/09: linha da arte no card da fila. painel_vendedor.html: arteBoxHtml/uploadArteCaixa/subirArteArquivo (storage shim → /api/arquivos/data-url, pasta orcamentos/arte/<vendedor>, nome com extensão), payload arte/arteVersoes, wrapper com orcamentoId, modal-ajuste-vend (ajustarOrcamentoVend, ajvRecalc, ajvSalvar → s.ajusteVendedor + enviarSolicNuvem), ajvTrilhaHtml/ajvRev/ajvCarimboHtml. Teste: node tests/ajuste-vendedor.test.mjs (107 checagens, 7 mutações acusadas, números reais do Nº 0017).
v2.37.920
🕳️
CRONOGRAMA SEM BURACO — a raia inteira preenchida — e 🔢 o nº do operador na MESMA ordem do PCP.
Pedidos do dono em
23/09/2026:
"tem um buraco no cronograma! Tem que estar tudo preenchido; se a fábrica fica parada por falta de programação tem que estar preenchido também; se tiver sem apontamento tem que aparecer sem apontamento — assim temos todas as informações. Sem perder nada." e
"na tela do operador os números estão todos fora de ordem, tem que seguir a ordem!". Preview aprovado (
"pode fazer").
📌
O que estava acontecendo: (1) a raia só desenhava o que tinha apontamento — o tempo em branco não dizia se a máquina parou sem programação ou se o pedido programado não foi apontado; (2) a barra do pedido concluído pegava a hora do progresso do app, que é apagado ao finalizar e recarimbado na volta da pausa — sobrando só a hora do FIM, ela era remontada com a duração do
plano (1h na tela pra um pedido que levou 2h); (3) eram DUAS réguas de número: o PCP numerava pelo plano congelado do dia e o tablet pela lista crua da Ordem de Produção — conferido em 23/09: o
NACON · 19 GRAN MESTRI-B era 13º no PCP e 1º no tablet.
✅
Raia preenchida: todo vão até "agora" (no 📼 Registro, o turno inteiro) vira
❓ SEM APONTAMENTO (o plano tinha pedido ali e ninguém apontou — o balão diz qual: "previsto aqui: 10º NACON 26 TABUAS (06:18→08:14)") ou
⏸ SEM PROGRAMAÇÃO (o plano não tinha nada). 🍽 almoço, intervalo e zona fechada continuam como eram; o 🔮 Previsão não ganha bloco.
✅
A barra segura o tempo real: vai do primeiro ao último apontamento do dia (lê os registros, não só o progresso). Pausou e voltou = dois pedaços, e o que rodou no meio aparece no lugar.
✅
Resumo: card novo
⏸ Máquina parada (sem apontamento · sem programação, por máquina). 🖨 Dia e 📅 Semana (impressão) saem com os mesmos blocos.
✅
Tablet: o nº do cartão é o MESMO do Cronograma (o plano do dia, lido da mesma API que o PCP grava, no login e a cada 10 min, com cópia no aparelho); a fila sai em ordem crescente do nº, com a seção
▶ EM ANDAMENTO · NA SUA MÁQUINA em cima e
📋 FILA · NA ORDEM DO PCP embaixo; o aviso "você está pegando fora da ordem" usa o mesmo nº.
✅
Nº estável: quem entra depois do congelamento é anexado ao fim do plano (concluir não renumera ninguém).
🔀 Reordenar no PCP passa a valer na hora, nas duas telas, pra quem ainda não começou — quem já rodou ou está rodando fica onde está (regra de 17/08: "o número só muda no próximo turno").
🔒
Não muda: nenhum apontamento, registro, quantidade ou horário; as barras que já apareciam (cor, nº, clique); a fila depois de "agora"; nada no banco nem na API — sem migration, sem restart. Máquinas cadastradas sem nada o dia todo (Die Cut, Facão, Integrada) ficam ⏸ o dia inteiro (era a opção recomendada no preview); a parada apontada pelo operador segue como contorno vermelho + card.
🔧 Por dentro: js/21-cronograma-inteligente.js (cronTrechosDoDia, cronEstadoReal(…, ds), cronPedacos, cronVaos, cronAnexarNovosAoPlano, cronAplicarReordenacao, card no cronRenderResumo, blocos no cronRenderLanes e no _cronPrintTimeline); js/110-numero-do-turno.js NOVO (jpNumeroDoTurno / jpDiaDoPlano, compartilhado com o tablet); painel_operador.html (_baixarPlanoDoDia, _opPlanoDoDia, _opNumeroFixo, ordenação da lista, pedidoForaDaOrdem, seções .fila-sec); js/01-core.js (o Salvar do 🔀 Reordenar chama cronAplicarReordenacao). Teste: node tests/cronograma-sem-buraco.test.cjs (61 checagens: registros → barra, vãos, tela/resumo/impressão, régua única, anexar, reordenar, portas do tablet).
v2.37.919
📅
A DATA DA ARTE TAMBÉM NA LISTA DE CAIXAS.
Pedido do dono em
24/09/2026:
"coloca a data na lista de caixas também" (era a pergunta em aberto do preview da v917).
✅
Cadastros → Caixas, depois de
🔎 Conferir artes no servidor: na coluna "Arte no servidor", ao lado do selo "PDF abre · 80 KB", aparece
"atualizada em 24/09/2026 08:02" — a data do arquivo no servidor, a mesma que a ficha do operador mostra. Arte que não está no servidor continua só com o selo vermelho.
🔒
Não muda: a coluna continua aparecendo só depois da varredura; nada é gravado.
🔧 Por dentro: js/109 (cxArteSeloHtml usa jpArteAtualizadaTexto). Teste: tests/arte-no-servidor.test.mjs (seção 7). Numeração: a v918 (trava da máquina) entrou na main enquanto esta frente andava; esta subiu como 919.
v2.37.918
🔒
UMA MÁQUINA, UM PEDIDO, UM OPERADOR — a trava que segura, a pausa automática e o sensor que só age pra quem está na máquina.
Pedidos do dono em
23/09/2026:
"faz a pausa automática quando entra outro pedido na mesma máquina" e, com os prints do celular,
"o que não pode acontecer é quando um operador está usando a máquina outro entrar no mesmo pedido, como aconteceu agora: está mostrando que o Arnaldo está usando, mas eu consegui entrar!". Preview aprovado (
"pode fazer").
📌
O que aconteceu na Slotter, pelo dado do servidor: às 19:10 o Arnaldo finalizou o KININO 20 (6.064 caixas registradas) mas o apontamento ficou "rodando" no servidor e o Mural mostrou "Arnaldo · KININO 20" a noite inteira; às 19:33 ele entrou no ajuste do NACON · 33 VIGOR; às 23:06 o celular do dono abriu o NACON · 26 TABUAS só pra olhar e às 23:09
o sensor iniciou a produção sozinho no nome dele (41 caixas); às 23:23 o Arnaldo pegou o 33 VIGOR de novo, mas a cópia da nuvem no celular do dono não viu isso, o card seguiu "🔧 EM ANDAMENTO" e às 23:45 ele entrou no pedido do Arnaldo. Três buracos: a trava confiava na cópia do celular (e um pedido já na lista nunca saía dela); o sensor não sabia quem estava na máquina; o pedido que ficou pra trás não pausava.
✅
Entrar: ao tocar num pedido, o app pergunta ao servidor
naquele instante quem está com ele (1 s, teto de 2,5 s). Outro operador vivo dentro → não abre, e diz quem e desde quando ("🔒 Em uso por Arnaldo (Máq. B Slotter) desde 19:33 — conferido no servidor agora"). Sem internet, vale a cópia do celular, como hoje — e o aviso diz isso.
✅
Pegaram o meu: se outro operador vivo pega depois de mim um pedido que estava na minha lista, ele sai da lista com aviso. Se eu estiver com ele
aberto em produção ou ajuste, ninguém tira o pedido da minha mão: o app avisa em vermelho, uma vez.
✅
Entrou outro pedido na máquina (🔧 ajuste, ▶ produção ou ↩ continuar, por qualquer operador): o que estava rodando nela
pausa sozinho no instante da entrada — tempo e contagem param ali. No mesmo tablet é na hora; em outro tablet, quando ele vir (4 s), com a hora certa da entrada, e o número de caixas tampado pelo que o sensor contou até ali. O tablet do pausado avisa e volta pra lista; o card dele diz "⏸ pausou sozinho às 19:33 · entrou NACON · 33 VIGOR (Arnaldo)".
✅
O sensor: "entra em produção sozinho" só roda no aparelho de quem está na máquina. Com outro operador vivo nela (em ajuste ou produção), quem só abriu pra olhar não ganha caixa nenhuma — e a tela avisa "🔒 Máq. B Slotter em uso por Arnaldo (33 VIGOR, desde 19:33)". Ajuste pausado por outro pedido também não vira produção sozinho.
✅
👁️ Só ver a ficha: no card travado apareceu o botão pra abrir a ficha técnica e a arte
sem pegar o pedido (sem trava, sem progresso, sem sensor), com a faixa "SÓ VISUALIZANDO · em uso por Arnaldo".
✅
Lista e Mural: o meu pedido pausado agora diz
⏸ PAUSADO na lista (dizia "EM ANDAMENTO"); no Mural, o pausado sozinho aparece com a hora e o motivo ("⏸ pausado atrás deste: KININO · CX 20 · 4.167 cx · pausou sozinho 19:33, entrou o NACON · 33 VIGOR").
🔒
Não muda: pedido largado (fim de turno, 🔓 do PCP) continua podendo ser continuado por outro, com o parcial; o operador com 2 máquinas continua (pedido de outra máquina não pausa o desta); nada é apagado do servidor. O "porteiro" no servidor (recusar dois operadores vivos no mesmo pedido, que precisa do Luan) fica pra depois, se ainda vazar.
🔧 Por dentro: painel_operador.html (_travaConferidaNoServidor + o toque do card async; travaDoPedido ganha desde; _outroPegouDepoisDeMim; a conciliação com a nuvem virou _reconciliarProgressosComNuvem, chamada pelo listener e pelo toque; _pausarOutrosNaMaquina no 🔧, no iniciarProducaoReal e nas voltas; _pausarPorOutroPedidoNaMaquina (retroativa, tampa o parcial pela marca do outro); _congelarTempoProd(pg, emIso) e _pausarPedidoAberto(pid, emIso, pausadoPor); _maquinaEmUsoPorOutro nas regras (0) e (1) do sensorAutomatico; statusVisualPedido → 'pausado'; abrirSoVer/abrirProducao(p, {soVer})/_aplicarModoSoVer; _atualizarAvisoMaquinaEmUso), js/38-mural.js (pausadoPor no sub e no rodapé). Teste novo tests/uma-maquina-um-pedido-um-operador.test.mjs (código real num vm, 7 mutações acusadas); contagem-para-com-o-pedido, o-pcp-decide-se-reprograma e sensor-age-sozinho ajustados na âncora. Sem servidor, sem migration, sem Luan.
v2.37.917
📅
A DATA DA ÚLTIMA ATUALIZAÇÃO, EMBAIXO DA ARTE.
Pedido do dono em
24/09/2026:
"quero colocar a data que atualizou, debaixo da arte: qual foi a data da atualização". Preview aprovado ("pode fazer").
✅
App do operador: embaixo do botão 📄 Abrir PDF da arte e embaixo da imagem da arte aparece
"atualizada em 24/09/2026 08:02" (data e hora). No visualizador, a data fica no cabeçalho ao lado do tamanho.
✅
Cadastros → Caixas → ✏️: na seção 📄 Arte PDF, a data ao lado do nome e do tamanho. Escolheu um arquivo novo e ainda não salvou:
"aguardando envio".
📌
De onde vem: é a data e hora
do arquivo no servidor, informada na mesma consulta que a ficha já faz ao abrir (a que descobre se a arte existe). Vale pra toda arte, nova ou antiga. Arte que não está no servidor fica com o aviso amarelo de sempre; sem resposta (wifi) não mostra data — nada é inventado.
🔒
Não muda: nenhum dado de caixa é gravado ou alterado; botões, medidas, cadastro e pedidos iguais; nenhuma consulta a mais.
🔧 Por dentro: js/109 (jpArquivoConferir guarda o Last-Modified em modificadoEm; jpDataHoraBr; jpArteAtualizadaTexto), painel_operador.html (carregarFichaTecnica: PDF e imagem; abrirPdf: cabeçalho), js/08 (modal da caixa + "aguardando envio" no onchange). Teste: tests/arte-no-servidor.test.mjs (seção 8, com mutação). Preview: claude.ai/artifact/83xR81XsaRiBLCfc5amktd
v2.37.916
🔢
A ARTE NOVA QUE "NÃO APARECIA": O ENDEREÇO GANHA NÚMERO DE VERSÃO.
Pedido do dono em
24/09/2026:
"servidor não está gravando as artes novas! A Gran Mestre já foi apagada várias vezes e não aparece".
📌
O que aconteceu, conferido no servidor: a arte da NACON · 19 GRAN MESTRI-B
estava gravada (676.322 bytes, igual ao PDF do Drive, às 08:00). Quem enganava era o
cache: o servidor manda o navegador guardar o PDF por
7 dias, e o endereço da arte era sempre o mesmo pra toda versão. Quem já tinha aberto a arte antiga (o PC, o tablet) continuava vendo a antiga depois da troca; parecia que não salvou, e a arte era apagada e anexada de novo sem a tela mudar.
✅
Agora: toda arte nova (PDF, imagem, foto do palete) grava o endereço com a
hora da gravação no fim (
?v=…) — um endereço que nenhum aparelho guardou, então a arte nova aparece na hora. As artes já gravadas ganham o número da versão atual ao carregar (uma vez, estável). O arquivo no servidor é o mesmo lugar de sempre; o servidor ignora o número na hora de achar o arquivo.
✅ As
11 artes do Firebase antigo (KININO CX 09/44/48, GRANJA HATTORI CX 01, NACON 04/08/16/23/26/27/34) foram
reanexadas pelo cadastro a partir do Drive e estão no servidor. A varredura 🔎 deve dar zero "sem resposta".
🔒
Não muda: nenhum arquivo apagado ou movido; cadastro, preço, medidas e pedidos iguais; o tablet só baixa de novo a arte que mudou. ❗ Não dá pra "limpar o cache do navegador a cada 30 s"; com o número de versão isso deixa de ser necessário.
🔧 Por dentro: js/109 (jpArquivoUrl preserva o ?v=; jpCaixaNormalizarArquivos põe ?v=<arteVersao> em link nosso sem versão), js/08 (subirConferindo devolve o link com ?v=Date.now()), api/src/lib/url-upload.js (o servidor não perde o ?v= ao devolver), scripts/anexar-arte-caixa.mjs. Testes atualizados: tests/arte-no-servidor.test.mjs, tests/arquivos-no-banco.test.mjs. Preview aprovado: claude.ai/artifact/33NpgETdTp4v1saDx1G88G
v2.37.915
🖼️
A ARTE DA CAIXA QUE SUMIU DO SERVIDOR — E AS 4 TRAVAS PRA NÃO SUMIR MAIS.
Pedido do dono em
23/09/2026, com o print do tablet:
"por que não consigo ver as imagens… o operador não consegue visualizar… foi testado em 2 apps e 2 aparelhos com o mesmo erro… coloca de uma maneira que não acontece mais isso!" (NACON · CX 33 FATIADOS: "⚠ Erro ao abrir PDF · Missing PDF", e "Erro 404" na aba nova).
📌
O que aconteceu, conferido no servidor: a caixa é de 03/06/2026 e o endereço da arte gravado nela era o do
formato antigo (sem o
/api/), que o sistema gerava até 10/06 e que
nunca abriu na KingHost — a correção de 10/06 valeu só pras artes novas. E o arquivo
não está mais no disco do servidor (a pasta das artes fica fora do git e fora do backup; a publicação foi refeita em 14–15/06). As artes de 29/06 em diante abrem. Nenhum código traz esse PDF de volta: ele estava no Google Drive do dono e volta pelo
scripts/anexar-arte-caixa.mjs (ou reanexando no cadastro).
✅
Trava 1 — endereço montado na hora: toda tela abre a arte pelo
caminho do arquivo, contra o servidor de agora. Endereço antigo sem
/api/, troca de hospedagem ou de pasta não matam mais a arte; as caixas de junho que ainda tiverem o arquivo voltam a abrir sem mexer no cadastro. O servidor faz o mesmo ao devolver as caixas (vale depois do restart).
✅
Trava 2 — só grava o que abre: ao salvar uma caixa com arte nova, o cadastro abre o endereço e exige que o servidor devolva o arquivo (mesmo tamanho). Falhou? A caixa fica
sem a arte nova e a tela avisa
"✗ A arte subiu mas o servidor não devolve o arquivo — a caixa NÃO foi salva com essa arte". O erro de junho teria aparecido no primeiro dia, na tela de quem salvou.
✅
Trava 3 — cópia da arte no banco: arte, imagem e foto do palete da caixa, arte/faca do orçamento, arte do portal e logo do cliente passam a ficar
também dentro do banco (que tem backup todo dia 12:30). Se o disco perder o arquivo, a API
recompõe sozinha ao reiniciar; as artes que já estão no disco entram no banco na primeira reinicialização. 🧰
Precisa do Luan: npm run db:migrate (migration 051) +
pm2 restart all. Até lá tudo funciona como antes.
✅
Trava 4 — aviso claro + varredura: no app do operador o cartão da arte já avisa
antes do toque "⚠️ Arte não está no servidor — pedir reenvio ao escritório" (só quando o servidor respondeu 404; wifi caído não vira "arte sumida"), e o visualizador mostra o que é e quem resolve — sem endereço de internet. Em
Cadastros → Caixas, o botão
🔎 Conferir artes no servidor pergunta caixa por caixa (PDF, imagem, palete) e lista só as que não abrem, cada uma com "✏️ abrir cadastro e reenviar"; a coluna "Arte no servidor" mostra ✓ abre · ✗ não está · endereço antigo. Só consulta.
🔒
Não muda: nenhuma caixa, medida, preço ou pedido; as artes que abrem hoje continuam abrindo do mesmo jeito e na mesma velocidade; o visualizador (pinça, zoom, páginas) fica como está; a varredura não apaga link nem arquivo.
🔧 Por dentro: arquivo novo js/109-arte-no-servidor.js (jpArquivoUrl · jpArquivoConferir · jpArquivoConferirSubida · jpArteSemServidorHtml · cxConferirArtesNoServidor), carregado pelo sistema e pelo operador; js/08 (migrarArtesParaStorage confere antes de gravar; aplicarCaixasRemotas/carregarCaixas normalizam; coluna na lista); painel_operador.html (_opCaixaSemHist, carregarFichaTecnica, _fichaArteSumida, abrirPdf); API: lib/arquivos-banco.js + lib/url-upload.js novos, routes/arquivos.js (cópia no banco), routes/caixas.js (normaliza ao devolver), index.js (sincroniza no boot); database/migrations/051_arquivos_no_banco.sql; scripts/anexar-arte-caixa.mjs. Testes: tests/arte-no-servidor.test.mjs e tests/arquivos-no-banco.test.mjs. Preview aprovado: claude.ai/artifact/W9YbSNAMoi2fCm2GmKvdY7
v2.37.914
📡
A CONTAGEM DO SENSOR PARA JUNTO COM O PEDIDO — E VOLTA DE ONDE PAROU.
Pedido do dono em
22/09/2026, com o print do Mural:
"o KININO 39 foi interrompido por problema de material, depois passaram várias caixas de vários pedidos, e quando voltou, voltou com a quantidade de todos que já tinha passado". Preview aprovado (
"pode fazer").
📌
O que aconteceu, com o dado do servidor: o "zero" do sensor do KININO · CX 39 foi anotado em
166.802 (Fabricio, 21/09 06:27). O Fabricio encerrou o turno com o pedido em 1 caixa e o zero ficou guardado. A Slotter rodou
7 outros pedidos em 2 dias (o contador foi a
196.306) e, quando o Arnaldo pegou o KININO de novo (22/09 20:59), o app fez 196.306 − 166.802 =
29.504 e escreveu isso no pedido em 2 segundos — num pedido de 5.000. A proteção da v2.37.811 só apagava o zero quando o fim do turno
creditava caixas; com 1 caixa já lançada não havia o que creditar. E a ⏸ pausa nunca mexia no zero.
✅
Saiu do pedido (⏸ Pausar, 🏁 fim do turno com ou sem crédito, 🔓 destravar do PCP, ⚠️ ocorrência de chapa): o tempo para (já parava)
e a contagem para junto. Fica no pedido o que o sensor tinha contado até ali.
✅
Enquanto está fora: o número do pedido
não mexe, no tablet nem no Mural, mesmo com a máquina rodando outros pedidos — o app não deixa nascer um zero novo pra pedido pausado.
✅
Voltou (↩ Continuar, pelo mesmo operador ou por outro): o app tira um
zero novo do sensor naquele instante e soma em cima do que o pedido tinha. A VIVA que parou em 598 volta em 598 e segue 599, 600…
✅
Mural: pedido pausado aparece
⏸ PAUSADO · contagem parada em N cx (azul, "há N min" desde a pausa); e
quem está rodando fica na frente do cartão — o pausado vai pro rodapé, com nome e quantidade (
"⏸ pausado atrás deste: KININO · CX 39 · 1 cx").
✅ A ⚠️ ocorrência de chapa dizia "pedido pausado" e só parava o cronômetro da tela; agora pausa de verdade (tempo + contagem, gravado).
🔒
Não muda: ▶ Iniciar produção continua entrando zerado (v667); o que o operador digita continua mandando (a correção na mão passa a entrar
dentro do zero novo, sem contar 2×); o apontamento dele segue sendo o número oficial;
"🔁 Ir pra outra máquina · este pedido continua rodando" continua rodando; nenhum registro já gravado é alterado; máquina sem sensor fica como está.
⚠️
O KININO de hoje: o parcial dele ficou em 29.504 no tablet do Arnaldo. Decisão do dono:
o Arnaldo digita a quantidade certa no campo — o app aceita e segue contando a partir dela.
🔧 Por dentro: painel_operador.html (_senFecharMarca/_senPatchMarcaFechada — a marca fechada num lugar só, sempre null explícito pro merge; _pausarPedidoAberto — ⏸ Pausar, o "pausar" do aviso de incompleto e a ocorrência pela mesma porta, com prodCongeladoEm novo; _liberarPgProProximo fecha a marca nos dois ramos; _acordarRelogios(pg, soCongelado, pid) mata o zero velho e chama _senRemarcarNaVolta, e o descongelar do aplicarEstadoProgresso usa a mesma conta; _marcarSensorNoProgresso zera qtdAjusteSensor ao remarcar e não ressuscita progresso; _senMarcarSeFaltar ignora pausado), js/61-sensor-contador.js (sensorDoPedido devolve null com prodCongelado), js/38-mural.js (⏸ PAUSADO em estadoDo; agruparPorMaquina põe quem roda na frente e lista pausados; rodapé do cartão; o Mural não grava marca de pausado). Testes: tests/contagem-para-com-o-pedido.test.mjs (64 checagens, 8 mutações acusadas, roda o js/61 real e o merge real da API), sensor-marca-morre-ao-largar virado (a marca morre nos dois ramos), sensor-age-sozinho ajustado. Sem servidor, sem migration, sem Luan.
v2.37.913
〰️
CADASTRO DE ONDAS PELA TELA — onda base, parede dupla e onda EXPOSTA.
Pedido do dono em
22/09/2026:
"se eu quiser fazer uma onda diferente, quero cadastrar isso, e isso ir para o cadastro da chapa e tudo mais" — e, no meio do caminho,
"existe onda exposta também: a EB teria 5 camadas, porém só tem 4; a capa externa não tem porque vai acoplado". Preview aprovado antes do código.
✅
Onde: 💰 Comercial → ⚙️ Config. Orçamento → Compensações por onda → botão
+ Nova onda. Você escolhe:
•
Onda base — com % da onda próprio (ex.: uma onda A a 40%);
•
Parede dupla — escolhe os 2 miolos, de fora pra dentro; cada miolo usa o % da linha da onda dele;
•
☐ Onda exposta — sem a capa de fora (vai acoplada numa folha impressa). A EB normal continua com 5 camadas; a exposta vira uma onda à parte (ex.:
EBX) com 4. A
folha impressa não entra no peso da chapa.
✅
A onda salva aparece sozinha no cadastro de Chapas (com as camadas certas), no de Caixas, no Orçamento (Maleta Normal / Meia Maleta / Aba Transpassada daquela onda), no corte e vinco, nas Ocorrências, no app do vendedor, no app do operador e no link do cliente ("Onda CE").
✅
✏️ em cada linha: a
compensação por aba da caixa (L1·C1·L2·C2·alt·lap), que antes só mudava no programa, agora se edita na tela — inclusive nas ondas de fábrica. Caixa nova já nasce com ela; caixa que existe não muda sozinha.
🔒
Nada se apaga: onda cadastrada se
desativa (sai das listas de escolher; chapa e orçamento antigos continuam lendo). A sigla, o tipo, os miolos e a "exposta" não mudam depois de salvos — as chapas guardam isso. O
↺ Restaurar padrão volta as ondas de fábrica ao número de fábrica e
não mexe nas que você cadastrou.
ℹ️
BB e BC passam a seguir o % da linha B (e C), como a EB — o número de hoje é o mesmo (35%). O app da onduladeira usa a média dos miolos na conta de kg por papel.
🔧 Por dentro: arquivo novo js/108-ondas-cadastro.js (janela, validação e jpOndasAplicar, que põe a onda cadastrada em CHAPA_ESTRUTURA, ONDA_LABEL, ESTILO_ONDA/LABEL, ONDAS_MALETA, COMP_ONDA_PADRAO e nos selects). A onda mora no ONDA_CONFIG (tipo, miolos, exposta, comp, nova, inativa), gravado por /merge keyed por onda. js/08: os miolos saem do cadastro (_ondaMiolos), _ensureOndas chama o js/108, o reset guarda as ondas cadastradas, o salvarConfigOrcamento diz se chegou. Apps: operador lê a espessura/nome no config_orcamento; vendedor e onduladeira já liam. Testes: node tests/ondas-cadastro.test.mjs (29 checagens, 8 mutações) e tests/onda-eb.test.mjs (15, 7).
v2.37.912
💬
CHAT — AS MENSAGENS PASSAM A MORAR NUMA TABELA DE VERDADE (fase 1 do Chat JP). Nada muda na tela.
Preview aprovado pelo dono em
22/09/2026 (
"pode fazer a fase 1"). Até aqui o chat inteiro era
um campo só, com as últimas
500 mensagens: a 501ª empurrava a mais antiga pra fora, calada — e o PCP já tinha 360 não lidas. Foto, áudio, "lido", responder: nada disso tem onde morar num campo assim. Esta versão é o chão.
✅
Tabela chat_mensagem, uma linha por mensagem, com a hora do servidor (
criado_em) além da hora do aparelho — o relógio do celular deixa de ser a única testemunha.
Tudo que já estava no chat entra na tabela (backfill); nada se perde.
✅
A tabela é a verdade, o campo antigo vira espelho. Quem grava — o PCP, o app do operador, o recado automático da vigia — grava nos dois
na mesma transação. Tablet em versão velha que ainda grava só no campo antigo é
absorvido pelo servidor: a mensagem dele chega na tabela do mesmo jeito.
✅
Sem teto: o PCP passa a ver as últimas
1.000 mensagens (era 500) e a tabela guarda todas. O "limpar chat" do admin
marca em vez de apagar (a linha fica, some da lista).
🔒
Nenhuma tela muda. Mesma aba Chat, mesmo botão 💬 no celular, mesmos 4 botões rápidos, mesmo aviso 🔴 de parada. Nenhum número de pedido, chapa ou preço é tocado.
🔧
Pro servidor (Luan): npm run db:migrate (migration
050_chat_mensagem, idempotente) e
pm2 restart.
Até rodar, o chat segue exatamente como era — o código pergunta ao banco se a tabela existe e, sem ela, usa o campo antigo.
🔧 Por dentro: database/migrations/050_chat_mensagem.sql (CREATE IF NOT EXISTS + backfill do blob com ON CONFLICT DO NOTHING; id legado = md5), api/src/lib/chat-tabela.js (instalada no padrão do app-sessao: 42P01 lembra por 60 s e pergunta de novo — se a API reiniciar antes do migrate, a tabela liga sozinha quando chegar e puxa o espelho (recuperarDoEspelho); outro erro não desliga; inserir(client) na transação de quem chama; absorver em lote pro PUT do app velho; listar com limite/operador/desde; apagarTudo = UPDATE apagado_em). Ganchos: routes/chat.js (POST/GET/DELETE), lib/vigia-alertas.js (inserirNoChat), routes/snapshots.js (PUT de chat_mensagens → absorver, depois do COMMIT, solto). Teste: tests/chat-mensagem-tabela.test.mjs (88 checagens, 6 mutações) + tests/chat-mensagem-tabela-banco.test.mjs (22, Postgres real via Docker).
v2.37.911
🔄
ATUALIZOU A PÁGINA, VOLTA NA MESMA TELA.
Pedido do dono em
22/09/2026:
"quero que quando eu atualizar eu volto na mesma página que estava". Antes, o F5 (e a atualização automática de versão) sempre voltava para a primeira tela, e você tinha que caçar no menu onde estava.
✅
Toda troca de tela fica guardada no endereço (
sistema.html#view=…). Apertou F5 ou o sistema se atualizou sozinho: depois do login, ele abre de novo a tela onde você estava — Config. Orçamento, Cadastro de Caixas, PCP, qualquer uma.
✅
Cada janela lembra a sua — quem usa duas janelas (⧉) em dois monitores não tem uma atrapalhando a outra.
🔒
Respeita o acesso: só abre a tela depois do login, e só se o seu perfil pode ver aquela tela. Ao
sair do sistema a tela é esquecida — quem entrar depois começa do começo, não na tela de quem saiu.
ℹ️ Volta a
tela. A sub-aba, os filtros e o que estava digitado num formulário aberto ainda não voltam (é o próximo nível, tela por tela, se precisar).
🔧 Por dentro: js/56-abas.js — lembrarNaUrl (history.replaceState, sem recarregar) em toda troca de tela; irPelaUrl passou a esperar o login (window.__permTabs) e conferir a permissão. js/12-offline.js — as 2 recargas de atualização mantêm o #view=. js/07-auth.js — logout e troca de usuário limpam o #view=. Teste: node tests/f5-volta-na-mesma-tela.test.mjs (9 checagens, 4 mutações).
v2.37.910
〰️
ONDA EB NO CADASTRO — parede dupla com um miolo E e um miolo B, cada um com o seu %.
Pedido do dono em
22/09/2026, com a foto da tabela "Compensações por onda":
"tenho que cadastrar uma onda EB, que seria a porcentagem de onda B e de onda E" — com a
E por fora (lado da impressão) e a B por dentro.
🔎
Por que não bastava uma linha a mais: a gramatura da chapa usava
um % só por onda — na BB e na BC os dois miolos entram com o mesmo 35%. Uma EB com um número só erraria a gramatura (e daí o peso e o preço).
✅
Na tabela de ondas (Orçamento ▸ Configurações) a EB aparece com espessura, comp/larg e altura editáveis (começa em 4,5 · 4,5 · 9). Na coluna
% da onda ela mostra
"E 32% · B 35%", lido das linhas E e B — mudou o % da E ou da B, a EB acompanha. Não existe número copiado.
✅
Gramatura: no cadastro de Chapas a EB tem 5 camadas (CAPA TOPO · ONDA E · MIOLO · ONDA B · CAPA BASE), e cada miolo entra com o % da onda dele.
BB, BC e as ondas simples dão exatamente o mesmo número de antes.
✅
A EB aparece onde BB e BC aparecem: onda da chapa e da caixa, Maleta Normal / Meia Maleta / Aba Transpassada (EB) no orçamento, corte e vinco, compensação por aba (começa igual à da BB — troque quando tiver os números da fábrica), app do vendedor, app do operador e link do cliente.
⚠️ Quem só trabalha com UM fator por chapa (programação da onduladeira, perda de papel, custo) usa a média dos dois (33,5%). A conta camada a camada, que é a da gramatura, é exata.
🔧 Por dentro: ONDA_MIOLOS = {EB:['E','B']} + fatorOndaDoMiolo(onda, n) e ondaPctTexto (js/08); calcularGramaturaChapa, gramaturaChapaImport e a composição da caixa contam o miolo; fatorOnda('EB') = média. A lista ['B','C','BB','BC'] estava escrita à mão em 5 lugares e virou ONDAS_MALETA. Teste: node tests/onda-eb.test.mjs (14 checagens, 6 mutações).
v2.37.908
🗂️
CATEGORIAS DE INSUMO NUM LUGAR SÓ — o app do Almoxarifado, os Pedidos de Compra, o Lançamento e a DRE leem do mesmo cadastro.
Pedido do dono em
22/09/2026, com o print do seletor "O que comprar" (Tinta, Fita, Cola, … e embaixo "Arame miruna, Paletes, Cola, Alça, Colagens externa, AMARELO DH 002"):
"vamos fazer as categorias — onde faz o cadastro de categoria tem que ser tudo em lugar só, para não ficar disperso e confuso".
🔎
Por que estava disperso: a categoria morava em
seis listas, quatro diferentes entre si — a fixa do lançamento (11), os insumos do orçamento colados nela (era daí que vinha "Cola" em dobro e "AMARELO DH 002" como categoria), as 8 gavetas do almox no sistema, as
5 gavetas do app do Almoxarifado (sem Cola, Fita nem Estilete — a cola só podia nascer como "Outro", e é por isso que a conferência de 21/09 achou
zero itens em cola e 7 em "outro"), a cópia da DRE e a do cadastro de fornecedores.
✅
Uma tela: 💰 Centro de Custo ▸ 🧰 Insumos do Orçamento ▸ card
🗂️ Categorias de insumo. Cada categoria diz: se é
gaveta do almoxarifado (cadastra item, tem saldo),
em que custo entra (parafuso, ferramenta e estilete somam em Manutenção — a DRE não muda), se o
cliente paga (faca, clichê), se
pede a máquina ou
o cliente. Dá pra criar ("Químico de tinta", "Verniz"), editar e esconder (🙈).
Nada se apaga: esconder só tira das listas de escolher; item e lançamento antigos continuam com o nome.
✅
Nenhum dado migrado. A chave gravada no item e no lançamento não muda; chave antiga vira apelido ("outro" = Outros, "fita" = Fita de arquear) e quem lê resolve. Os 7 itens em "outro" continuam onde estão — e agora dá pra mover cada um pra gaveta certa no app do Almoxarifado, que passou a oferecer
todas as gavetas do catálogo (Cola, Grampo / arame, Fita, Estilete…).
✅
"O que comprar" ficou limpo: só o catálogo (+ os rótulos que alguém digitou em "Gerenciar insumos"). Item ligado ao almox e insumo do orçamento (Paletes, Alça, Colagens externa)
não são categoria e saíram da lista. Insumo-rótulo sem gaveta agora diz:
"é um rótulo de insumo, não uma categoria — cadastre a categoria ou ligue ao almox" (a frase "não é item de estoque" pra Cola estava errada — achado §4.3 da conferência).
🔧 Por dentro: arquivo novo js/107-categorias-insumo.js (JPCat: padrão = a soma fiel das listas antigas; snapshot categorias_insumo = {cats:{key:…}} gravado por /merge chave a chave; resolve/gavetasDe/custoDe/cardHtml; dois transportes: apiFetch no sistema e db no app). Leitores: js/13 (catLancAll, catRotulo, catCusto, gavetasDaCat, _pcCatDoAlmox, CAT_FORA_CUSTO), js/31 (CATS montado do catálogo, filtro por chave resolvida), js/43 (DRE agrupa por custoDe), painel_almoxarifado_jpe.html (preencherCatsItem, CAT do catálogo). As listas fixas ficaram como RESERVA pra quando o js/107 não carrega. Testes: tests/categorias-insumo-um-lugar-so.test.mjs (27 regras, inclusive "as listas antigas deixaram de ser cadastro") e compras-categoria-estrita (30, agora rodando com o catálogo real).
v2.37.907
🛒
COMPRAS — "Cola" não lista mais tinta, a tela diz o que está faltando, e o que chegou entra no estoque uma vez só.
O dono viu em
21/09/2026: "O que comprar = Cola" e o seletor de produto listando AMARELO DH 002, ARAME MIRUNA, ANTI ESPUMANTE — o almoxarifado inteiro.
"as categorias está tudo bagunçado".
🔎
Por que a categoria não mandava: o seletor tinha um "consolo" desde a v2.37.170 — categoria sem item no almoxarifado (ou sem mapeamento)
mostrava tudo, "pra nunca deixar o seletor vazio". Cola sem gaveta no almox = as 63 tintas na lista. Seletor cheio de coisa errada é pior que vazio: o pedido saía com a categoria de custo errada, sem ninguém ver.
✅
A categoria manda. Cola lista só cola; tinta só tinta; manutenção abre parafuso, ferramenta, estilete e "outro". Categoria que não é de estoque (clichê, frete, energia, mão de obra) fica vazia e
a tela diz por quê: "Clichê não é item de estoque — peça em outro (digitar na mão)". Gaveta sem item cadastrado também diz: "nenhum item de Fita de arquear cadastrado no Almoxarifado · Cartonagem — cadastre lá". O "outro (digitar na mão)" continua em todas.
✅
"já pedido" ao lado do estoque. "AZUL DH 007 — tem 0 kg (mín 3) · 50 kg já pedido": o que está com o comprador aparece no seletor, e o ⚠️ abaixo do mínimo passou a contar
tem + já pedido — tinta zerada com 40 kg a caminho não está faltando, está chegando. Era assim que se pedia duas vezes.
✅
Caixa "⚠️ O que está faltando" no alto da tela: todo item com mínimo cadastrado cuja soma (tem + já pedido) está abaixo dele, o mais crítico primeiro, com a
quantidade sugerida (repõe até 2× o mínimo, arredondada na embalagem) e o fornecedor.
➕ pôr na lista põe no pedido com a categoria de custo certa.
🔎
Por que o estoque podia somar duas vezes: quando a compra chegava, o Lançamento de Insumos mandava somar no almoxarifado — e cada movimento do livro nascia com um id
aleatório, que por construção nunca repete. Nada no sistema sabia dizer
"isto eu já somei". Rede caiu no meio da baixa? Clicou duas vezes? O saldo somava duas vezes, calado. É a mesma família do estoque que volta.
✅
Cada recebimento tem nome agora. A entrada vindo de um pedido carrega uma chave que descreve
o fato ("a 1ª entrega do item 2 do pedido OC-0010"), não o clique. Salvar o mesmo recebimento duas vezes soma
uma. Se a gravação do saldo falhar no meio, a chave fica livre pra tentar de novo — material que chegou não pode sumir.
✅
📦 Receber por linha (recebimento parcial). Chegou 60 dos 100 kg de arame? Agora cada linha do pedido mostra
quanto foi pedido, quanto já veio e quanto está chegando agora. O que falta continua no pedido, que fica
"chegou em parte", e o "já pedido" da tela de compras cai sozinho de 100 para 40 — não se pede de novo o que já está na prateleira. Receber mais do que faltava é permitido, mas
pede o motivo, que fica gravado no histórico do pedido.
✅
Custo médio do insumo. Toda entrada de compra atualiza o custo médio ponderado do item: 240 kg a R$ 20 + 60 kg a R$ 25 = R$ 21,00 o quilo. Item que ainda não tinha custo médio começa pelo preço cadastrado. O custo anterior fica guardado no movimento — dá pra responder "por que este custo mudou".
O que não muda: quem lança na mão, sem pedido, continua exatamente como antes. O app do comprador não precisa de nada novo (ele ignora o que não conhece). Sem servidor, sem Luan, sem migration.
🔧 Por dentro · js/13-custos.js: CAT_ALMOX_DE virou mapa categoria → gaveta(s) do almox, gavetasDaCat / itensDaCat estritos (o fallback doTipo.length?doTipo:todos saiu), itensDaCatVazio, _pcFaltando / _pcCaixaFaltando / ccPcPorFaltando, _pcCatDoAlmox; _ocQtdPedida / _ocQtdRecebida / _ocQtdFalta e OC_EM_ABERTO (o _pcEmAberto desconta o recebido), ccOcReceber (o painel), _ocChaveEntrada (oc:<id>:<linha>:r<entrega>), _ocAplicarRecebimento — que grava pelo jpAtualizarOrdemCompra, ou seja continua uma gravação por pedido. · js/31-almox-cartonagem.js: jpAlmoxEntrada(itemId, delta, quem, {chave, origem, precoUnit}) — reserva a chave no livro antes de mexer no saldo, devolve {repetido:true} se já somou, marca falhou se o saldo não gravou; _custoMedioNovo. Sem chave o caminho é byte a byte o de antes. ⚠️ O que isto não resolve: dois aparelhos somando no mesmo segundo — o doc do estoque é uma lista gravada por PUT inteiro e o livro não tem compare-and-set. Testes: tests/compras-categoria-estrita.test.mjs (28 regras) e tests/compras-recebimento-idempotente.test.mjs (26 regras, servidor de mentira com GET/PUT/merge de verdade). Modelo do ciclo de compras e os relatórios das duas fases em cartonagem2-docs/compras/.
v2.37.906
📦
Orçamento: o desenho do palete voltou a acompanhar o lastro — e orçamento novo não traz mais o palete do cliente anterior. Três coisas na mesma tela.
1 · O desenho que não acompanhava o lastro.
Dono em
21/09/2026:
"o desenho dos paletes não está acompanhando o lastro". Na foto, o painel dizia
lastro 6 pacotes (amarração, overhang 100 mm, base 964 × 1.377 mm) e o cabeçalho
🖼️ Ver o palete dizia
6 × 7 = 1.050 cx — mas os três desenhos logo abaixo mostravam
4 pacotes em caracol, com "overhang 60mm" escrito dentro do próprio desenho. Número novo em cima, desenho velho embaixo, na mesma caixa.
🔎
O desenho não estava errado: estava PARADO. O 🖼️ Ver o palete é um painel dentro do painel 📦 Paletização, e a regra de estilo que abre um painel abria junto o de dentro. Ou seja: ele aparecia
aberto na tela (corpo à mostra, setinha virada) enquanto o sistema continuava achando que estava
fechado — e painel fechado, de propósito, não redesenha (são 140 KB de desenho a cada tecla; é pra isso que existe o clique). Resultado: os números seguiam a conta e os desenhos ficavam no último estado desenhado, cada tecla aumentando a distância.
✅
Agora abrir o 📦 Paletização não abre mais o 🖼️ Ver o palete sozinho. Ele começa fechado, a setinha diz a verdade, e no clique abre desenhando o palete de
agora — e segue acompanhando cada mudança de medida, amarrado, palete ou overhang.
ℹ️
Nesta parte nenhum número mudou — caixas por palete, paletes e preço são os mesmos de antes. O que estava errado era só o desenho parado.
🚨
2 · Orçamento novo vinha com o palete do cliente ANTERIOR — e isso mexe no preço.
Dono, no mesmo dia:
"toda vez que for iniciar um orçamento ele vem limpo, sempre limpo — eu estava fazendo um novo orçamento e veio informação de outro cliente, o cliente anterior".
🔎
Eram seis campos, e só eles. Os ajustes de palete
desta caixa — peças por amarrado, altura máx. do palete, palete L×C, lastro, overhang máx. e a caixinha ⚠️
palete FORA do padrão — eram preenchidos ao
editar um item e
ninguém nunca os apagava. Começar um orçamento novo trazia os seis do cliente anterior, e eles passam por cima do padrão de ⚙️ Config. Orçamento: mudam
caixas por palete → número de paletes → frete, sem avisar. Varri o formulário inteiro campo a campo:
todo o resto já nascia limpo — eram esses seis.
✅
Agora saem junto com o resto, tanto ao abrir um orçamento novo quanto ao passar de um item pro outro — a própria tela promete que eles "valem só para esta caixa". Vazio volta a significar
o padrão da Config. Orçamento, e ao reabrir um item os ajustes gravados NELE voltam normalmente.
⚠️
Orçamento já salvo não se conserta sozinho: se algum saiu com o palete de outro cliente, o número de paletes dele ficou como foi gravado. Vale reabrir e conferir os que te parecerem estranhos.
⚡
3 · De quebra: com o 📦 Paletização
fechado, o sistema ainda montava os 140 KB de desenho a cada tecla das medidas — pra ninguém ver. Agora só desenha o que está de fato na tela, e abrir a gaveta já traz o desenho do momento.
🔧 Por dentro: sistema.html — as duas regras do .opal (.opal.aberta .opal-corpo e .opal.aberta .opal-seta) passaram a ser de filho direto (>). Com seletor descendente, o #orc-pal-des-box — que mora dentro do corpo do #orc-pal-box — era aberto pelo pai enquanto o ORC_PAL_DES_ABERTO continuava false, e o _orcPalDesenhar escrevia o cabeçalho e caía fora antes dos três SVGs. Teste tests/painel-aninhado-nao-abre-sozinho.test.mjs — roda no Chrome de verdade com o CSS e o bloco de HTML recortados do próprio sistema.html (é cascata: DOM de mentira não pega): 22 checagens, 1 mutação. · js/08-cadastros.js: _orcPalDesenhar só desenha com a gaveta de cima aberta e orcPalAbrir chama o painel de volta; orcPaletesLimpar passou a apagar os seis campos orc-pal-* — é a função que as duas portas de reset já chamavam (§9.13). A régua da herança (tests/orcamento-nao-herda-item.test.mjs, da v890) varria só os ids orc-it-* — por isso os orc-pal-* nunca foram conferidos; agora varre os dois e mede caixinha por checked: 22 checagens, 10/10 mutações acusadas. Sem servidor, sem Luan.
v2.37.905
🔁
Operador finalizou? O pedido sai da tela dele e vem pra VOCÊ decidir se reprograma.
Dono em
21/09/2026:
"quero que no app do operador, se ele der como finalizado, sai da tela e entra pro PCP decidir se vai reprogramar ou não" — e o motivo:
"porque está ficando pedido em aberto".
O que estava acontecendo. Quando o operador finalizava sem bater a quantidade, havia dois caminhos e nenhum dos dois chegava até você:
· o botão roxo
"🔄 GRAVAR e PASSAR pro próximo operador" deixava o pedido
aberto na lista do tablet — e se ninguém pegasse, ele ficava lá;
· o
"acabou mesmo" tirava o pedido do tablet, mas no PCP ele ficava parado em
"Em produção", sem aviso nenhum, até alguém reparar.
Como ficou. Finalizou faltando caixa (mais de 5% do pedido, a folga de sempre pra apara e defeito) → o pedido
sai da produção e acende a
tarja vermelha lá em cima:
"⚠ N PEDIDOS COM PRODUÇÃO PARCIAL · AGUARDANDO SUA DECISÃO", com os três botões de sempre —
aceitar o parcial,
continuar o mesmo pedido ou
gerar pedido novo com o que falta.
✅
O sistema não reprograma mais nada sozinho (era a v2.37.729, de 08/09): agora quem decide é você, também quando a chapa acaba.
✅
No tablet ficou um caminho só: quem finaliza, finaliza. O botão roxo saiu. Quem larga o pedido no meio usa
⏸ Pausar ou o
🏁 Fim do turno — o que ele fez continua gravado no nome dele e o pedido continua na lista pro próximo.
✅
A chapa que está no chão não se joga fora. No "continuar o mesmo pedido": se a chapa acabou, ela zera e você lança a nova; se ainda tem chapa lançada,
ela fica e o pedido volta direto pro operador terminar — sem você ter que lançar de novo papel que já está na fábrica.
O que NÃO muda: produção, paletes, etiquetas e apontamentos ficam como estão (nada é apagado), e pedido já carregado ou entregue não é tocado.
⚠️
Na primeira vez pode vir uma fila. Os pedidos que já estavam parados assim vão aparecer na tarja conforme a tela roda — é a bagunça que já existia ficando visível, não bagunça nova.
🔧 Por dentro: processarFinalizacaoPedido (js/02) marca aguardandoDecisaoPcp + statusOp='pronto' em vez de reprogramar sozinho (ou ficar mudo) — e não toca mais na chapa; conclusão com 0 produzido é fantasma (marca velha do documento publicado) e não tira ninguém da tela do operador. jpChapaAcabou (js/01) é a conta da chapa em UM lugar só — a mesma régua do _saldoDaEtapa do tablet — e o "continuar" da tarja passou a delegar pro _aplicarReprogramarContinuar (eram duas cópias, e só a de lá soltava a trava do operador). No painel_operador.html saíram o botão fim-inc-passar, a fiação e o _passarProProximo inteiro. Testes tests/o-pcp-decide-se-reprograma.test.mjs (45 checagens, 14 mutações) e tests/sair-do-pedido-uma-vida.test.mjs (45 checagens, 15 mutações). Sem servidor, sem Luan.
v2.37.904
🧊
O 3D da TANGARA voltou (dizia "o desenho veio vazio") e o EPS parou de ser recusado pelo Illustrator. Dois defeitos, um de cada lado.
1 · O 3D de toda caixa com faca em DXF estava morto. Dono em
21/09/2026, na 04 FLOPS 70:
"o 3D da TANGARA não está aparecendo". Existem duas formas de linha no sistema — a do desenho por fórmula e a da faca em DXF já classificada em corte, vinco e picote (v2.37.895) — e o conversor do motor 3D só entendia a primeira. Com a segunda,
toda linha era descartada e a lista chegava vazia. Só quebrava caixa com DXF; caixa por fórmula ia pelo outro caminho e funcionava, e foi por isso que passou despercebido desde a v895. Agora o conversor entende as duas formas, e polilinha de vários pontos vira os segmentos certos.
2 · O EPS: "abre no Photoshop e não abre no Illustrator". Foi esse dado do dono que fechou o caso. O PostScript estava válido — tanto que o Photoshop roda —, mas o leitor de EPS do Illustrator é de
nível 1 e não conhece
setcolorspace nem cor especial por
/Separation, que era como o arquivo pintava corte e vinco. O arquivo de referência que ele mandou prova: não tem nenhum
setcolorspace e define o próprio
setcmykcolor. Agora o EPS faz igual,
só nível 1: corte preto 100%, vinco vermelho, cada um em CMYK direto. Selecionar ▸ Mesma ▸ Cor do traço continua funcionando.
✅
Saiu também o %AI5_ArtSize que eu tinha posto na v901 pra tentar fixar a prancheta: é comentário privado do Illustrator e, num arquivo que não é nativo dele, atrapalha em vez de ajudar — e nem funcionava.
ℹ️
O PDF não mudou e continua sendo o recomendado: camadas FACA / COTAS / ARTE, prancheta com folga e a faca exata marcada no TrimBox.
🔧 Por dentro: js/69-caixa3d-motor.js (entsDoDesenhoReal aceita {t,c,x1,y1,x2,y2} e {cor,pts} — o conversor é o funil dos dois caminhos); js/106-faca-eps.js (EPS sem /Separation, sem %%LanguageLevel, sem %AI…, com setcmykcolor definido no prólogo quando falta). Testes: tests/caixa3d-motor.test.mjs (41 checagens, 14 mutações — a prova passou a exercitar os dois formatos) e tests/faca-em-eps.test.mjs (91 checagens, 18 mutações).
v2.37.903
🖨️
Romaneio pelo sistema: a janela não fica mais muda em "Gravando…".
Foto do dono em
20/09/2026, 22:48: a janela de impressão do Chrome com uma página em branco só com a frase "Gravando o romaneio no servidor…", e depois "não abre mais nada". Eram três defeitos em fila, no caminho do
sistema (o do app foi a 872):
1. Ao pedir o romaneio de uma carga que
já tem romaneio (a GAIOTO tinha o nº 95), o sistema abre a janela nova
na frente, escrita "gravando…", e faz a pergunta
"2ª via ou número novo?" na aba de trás. Quem está olhando a janela nova acha que travou. Agora a pergunta aparece
dentro da janela que a pessoa está olhando (e continua na aba do sistema, pra quem ficou nela), e a janela diz o que está fazendo de verdade: "lendo o histórico", "gravando", "preparando o papel".
2. Quando o papel chegava, ele era
anexado à frase de espera em vez de substituí-la (o Chrome anexa quando o documento é deixado aberto): o romaneio impresso pelo sistema saía com "Gravando o romaneio no servidor…" escrito em cima e com o título errado. Medido no Chrome. Agora o papel substitui tudo — vale pros outros documentos que usam a mesma janela.
3. Se a pessoa fechasse a janela antes de escolher, a escolha feita depois escrevia e mandava imprimir
numa janela fechada: nada acontecia. Agora cai na impressão por dentro do sistema, com aviso.
O que não muda: número, 2ª via, cancelamento e o papel em si. Sem servidor, sem Luan.
🔧 Por dentro: js/24-romaneio.js (_romAbrirJanela fecha o documento e diz "lendo o histórico"; _romJanelaDiz; romEscolherRomaneio espelha a escolha em info.janela, mesma promessa; abrirRomaneioCargaCliente passa a janela) · js/68-papel.js (entregar: document.open() antes do write e janela fechada cai no iframe com aviso próprio). Teste tests/romaneio-janela-nao-fica-muda.test.mjs — roda no Chrome de verdade (popup, document.open/write/close e closed são coisa de navegador): 22 checagens, 5 mutações.
v2.37.902
📐
A faca agora CABE na prancheta, com folga — e as cotas foram pra margem, fora da área de arte.
Dono em
20/09/2026, na 2ª foto:
"ficou do mesmo jeito, tem que caber dentro da prancheta e com folga pra cima e para o lado".
✅
A prancheta virou a faca mais uma margem igual nos quatro lados (10 a 50 mm, conforme o tamanho da chapa). A faca fica centrada. Na caixa da FK GRUPO: prancheta 2.365 × 978 mm pra uma faca de 2.265 × 878, com 50 mm de folga em volta.
✅
As cotas saíram de cima do desenho e foram pra margem — os painéis embaixo, as faixas nos dois lados, o total em cima, e o nome do arquivo no canto. É onde o arquivo do ArtiosCAD também as põe. Continuam na camada COTAS, então some tudo de uma vez.
✅
O PDF guarda a faca exata no TrimBox. Assim a prancheta tem folga pra trabalhar, mas o sistema continua sabendo qual é a medida verdadeira da faca quando a arte volta — é do TrimBox que ele tira.
⚠️
Sobre o EPS: ele pede a prancheta certa, mas o Illustrator só obedece esse pedido em arquivo nativo dele — por isso o EPS ainda abre numa prancheta padrão. No PDF a página
é a prancheta, e é por isso que o botão grande é o PDF.
🔧 Por dentro: js/106-faca-eps.js — folga(maiorLado) (10 a 50 mm), a faca deslocada pra dentro nos dois formatos, cotas posicionadas na margem, e /TrimBox no PDF marcando a faca dentro do /MediaBox. Conferido renderizando o PDF: prancheta 2.365 × 978, faca 2.265 × 878, folga 50 mm nos quatro lados. Teste tests/faca-em-eps.test.mjs (90 checagens, 17 mutações).
v2.37.901
📐
A faca agora sai em PDF com CAMADAS de verdade — prancheta do tamanho do desenho, cotas em camada separada e o nome do arquivo dentro.
Pedido do dono em
20/09/2026, com o EPS já aberto no Illustrator:
"sempre que mandar, manda o artboard do mesmo tamanho do desenho; e a layer cotas separada, pra ficar fácil de apagar; e coloca o nome do arquivo dentro da layer".
🔎
O que a foto dele mostrou: o EPS abriu, mas o Illustrator montou uma prancheta
padrão em vez da faca. Faltava o
%AI5_ArtSize, que é o que fixa a prancheta — o arquivo de referência dele traz. (Um dos auditores tinha avisado e os três céticos o derrubaram; quem desempatou foi a tela.)
✅
Camada de verdade só existe em PDF. Em EPS, camada exige o código da Adobe embutido no arquivo (~1.300 linhas) — foi justamente isso que travou a v2.37.899. Em PDF é nativo, e o Illustrator abre igual. Então o botão passou a ser
📐 Faca (PDF): prancheta = a faca, exata, e três camadas no painel —
FACA,
COTAS (com o nome do arquivo dentro, é só apagar a camada) e
ARTE, vazia, pra desenhar. As cores especiais continuam: Corte, Vinco e Cotas.
✅
O EPS continua, no botão pequeno ao lado, agora com a prancheta certa — mas sem camada, que é limitação do formato.
✅
O traço acompanha a chapa: meio ponto numa prancheta de 2,2 m é invisível; agora a espessura cresce com o desenho.
🔧 Por dentro: js/106-faca-eps.js — jpFacaPdf (PDF 1.5 escrito à mão: /OCProperties com os três OCG, /OC /OCn BDC por camada, MediaBox = a faca, separações por /Separation com função de tinta tipo 2, e o xref montado com o deslocamento real de cada objeto), jpBaixarFaca(cx, 'pdf'|'eps') e orcBaixarFaca(fmt); o EPS ganhou %AI5_ArtSize e o nome do arquivo no desenho. Conferido de fora: o macOS renderizou o PDF e leu a página como 6420 × 2489 pt = 2265 × 878 mm. Teste tests/faca-em-eps.test.mjs (84 checagens, 15 mutações). Sem servidor, sem migration, sem Luan.
v2.37.900
📐
O EPS da faca agora ABRE no Illustrator — e o desenho passou a bater com a prancheta.
O dono, sobre o arquivo da v2.37.899:
"quando eu abrir o eps" →
"Não é possível concluir a operação em função de um erro desconhecido". Ele mandou junto um EPS que abre (ArtiosCAD 24.03 → Illustrator 8) pra comparar.
🔎
Por que não abria: o arquivo usava os comandos de camada do Illustrator (
Lb,
Ln,
LB) sem trazer o código da Adobe que os define — sem ele são comandos que não existem, o interpretador para no meio e o Illustrator só diz "erro desconhecido". E o cabeçalho tinha traços e acentos num arquivo que se declarava de 7 bits.
✅
Agora sai no dialeto do arquivo dele: PostScript puro, 7 bits,
sem camada nenhuma — o ArtiosCAD também não usa. A separação é por
cor nomeada:
Corte em preto 100% (o "Artios_Recortar" dele),
Vinco em vermelho tracejado (o "Artios_Vinco") e
Cotas em azul. Pra travar a faca: Selecionar ▸ Mesma ▸ Cor do traço, e bloquear — está escrito dentro do arquivo.
✅
A prancheta virou o desenho, exatamente. A aba de cola era desenhada a partir de 6 mm e sobrava uma faixa vazia: a prancheta dizia 2.265 e o desenho media 2.259. Agora a aba começa no zero e a cota de 35 tem 35 de verdade.
✅
As cotas entraram pra dentro da prancheta. Antes eram pintadas fora dela, e o que fica fora é recortado na hora de colocar o arquivo. Elas vão na cor Cotas, com a letra no tamanho do desenho: dá pra selecionar todas e apagar antes de mandar a arte.
✅
Os rasgos abrem de verdade. O contorno passava reto por cima da boca dos rasgos entre as abas, e o vinco horizontal atravessava os três — linha de corte e de dobra onde não há papelão. Agora a borda e o vinco se interrompem em cada rasgo, e o contorno fecha sem ponta solta.
✅
A maleta deixou de sair espelhada: a aba de baixo encosta no zero, o corpo fica no meio e a aba de cima no topo. Era por isso que a
meia maleta saía sem a aba de baixo em vez de sem a de cima, e o 3D escolhia o fundo errado.
🧪
Como foi conferido: cinco auditorias independentes compararam o arquivo com o EPS que funciona, e cada achado foi atacado por três céticos. Os sete que diziam "isto impede abrir" caíram por unanimidade — o formato está certo. Sobraram estes cinco, todos corrigidos. Além disso: um simulador roda o PostScript comando a comando (nenhum comando indefinido, pilha fecha limpa), o arquivo é 7 bits puro e nada é pintado fora da prancheta.
🔧 Por dentro: js/106-faca-eps.js — jpFacaDaMaleta reescrita (Y pra cima, aba de cola no zero, segmentosSemRasgos abrindo borda e vinco, faixas de baixo pra cima, devolve abaInf); jpFacaEps sem %AI5_BeginLayer, com /Separation por cor, tudo 7 bits (ascii()) e cotas dentro do BoundingBox com a letra proporcional. js/101 acha o fundo pela aba de baixo que a faca informa. Teste tests/faca-em-eps.test.mjs (64 checagens, 11 mutações, uma delas combinada). Sem servidor, sem migration, sem Luan.
v2.37.899
📐
A FACA SAI EM EPS PRO ILLUSTRATOR — e a arte volta encaixada, sem erro no 3D.
Pedido do dono em
20/09/2026, com o arquivo da FK GRUPO na mão:
"essa é uma arte, ela tem que encaixar na arte da faca. Quando a gente cria a caixa no sistema, tem o modo de exportar EPS pra abrir no Illustrator, pôr a arte e devolver aqui — e a arte encaixa certinho no 3D. Assim não tem erro, porque já temos o DXF e depois a arte encaixada." E o destino:
"usamos esses arquivos pra mandar pra clicheria depois de todos os clientes aprovados".
🔎
Por que o 3D saía torto: a caixa era montada por
fórmula simétrica (comprimento + compensação igual dos dois lados) e a arte é desenhada sobre a
faca real da máquina, com painéis diferentes entre si — na FK GRUPO, 579 e 581, 536 e 534. Duas molduras diferentes: a arte nunca caía certa. A saída não era calibrar melhor, era o sistema
entregar a moldura.
✅
Botão 📐 Faca em EPS na janela da caixa e no item do orçamento. O arquivo abre no Illustrator com a
prancheta do tamanho exato da faca e três camadas:
FACA (corte contínuo, vinco tracejado, picote pontilhado — travada e sem impressão),
COTAS (os números do desenho: 35 · 579 · 536 · 581 · 534, as faixas 268 · 342 · 268 e o total 2265) e
ARTE, vazia, pra desenhar. O recado vai dentro do arquivo: não mexa na prancheta nem na camada FACA.
✅
A faca da maleta sai das medidas do cadastro, painel a painel, com a compensação de cada um — não mais simétrica. Sem compensação salva ela sai sem, porque é o que está gravado (quem cobra é o aviso da v2.37.857). Corte e vinco sai do DXF, com as linhas já classificadas.
✅
O 3D passou a usar a MESMA moldura do EPS. É isso que faz a arte encaixar painel por painel.
✅
Quando a arte volta, o sistema confere:
"✅ arte encaixada na faca (2265 × 878 mm)" ou
"⚠️ a arte não está na moldura desta caixa: arte 210 × 297 mm, faca 2265 × 878 mm — baixe a faca em EPS e encaixe a arte nela". No cadastro da caixa e na barra da arte do orçamento.
Avisa, nunca barra.
🔁
Aprovação e clicheria seguem como já eram: o arquivo devolvido é a arte da caixa, com versão, vai pro portal do cliente e pra ficha da clicheria. O EPS é a moldura de trabalho; o que roda é o que voltou com a arte.
🔧 Por dentro: arquivo novo js/106-faca-eps.js (jpFacaDaMaleta — a faca pelas medidas do cadastro; jpFacaEps — EPS 3.0 com BoundingBox em pontos e as camadas do Illustrator pelo operador Lb; jpArteEncaixaNaFaca — folga de 2 mm; jpBaixarFacaEps / orcBaixarFacaEps). O js/101 passou a montar a maleta por essa faca e expõe a geometria da tela; o js/08 ganhou o botão, o cxCaixaDoForm (dá pra exportar antes de salvar) e o aviso de encaixe. Teste tests/faca-em-eps.test.mjs (45 checagens, 6 mutações, todas acusadas), com os números da arte real da FK GRUPO. Sem servidor, sem migration, sem Luan.
v2.37.898
📏
Limites por máquina, agora POR FUNÇÃO: a máquina que faz corte e vinco E slotter (Die Cut) tem um jogo de limites pra cada modo.
Dono,
20/09/2026, vendo a tela da 889:
"temos máquina, como eu havia falado, que tem as 2 funções — esse caso que é modo slotter e modo corte e vinco".
🔎
O que era: um conjunto só de limites por máquina (v2.37.889). Na Die Cut, chapa e caixa de um modo se misturavam com o outro.
✅
Funções da máquina: na máquina de corte, dois ✓ — 🖨️ Slotter (caixa de dobra) e ✂️ Corte e vinco. A Máq. B Slotter é só Slotter e a Máq. A só Corte e Vinco (fixo); a Die Cut marca as duas. Máquina cadastrada sem função marcada segue a régua da rota: "corte" ou "vinco" no nome é C&V, senão Slotter.
✅
Um bloco de limites por função: "🖨️ modo Slotter" e "✂️ modo Corte e Vinco", cada um com chapa e caixa, mínimo e máximo; Coladeira, Grampeadeira e processos do meio têm um bloco só. Os blocos aparecem e somem conforme a posição no fluxo e as funções marcadas; desmarcar uma função tira os limites dela. O chip da lista mostra cada modo com o seu ícone.
✅
A caixa escolhe o modo: caixa de dobra é conferida no modo Slotter, caixa de corte e vinco no modo Corte e Vinco — no cadastro da caixa, no orçamento (pelo estilo do item) e na lista de Caixas. Máquina de uma função só vale pra qualquer caixa (ela só roda de um jeito); máquina de duas funções só responde pelo bloco do modo — sem ele, diz "sem limites cadastrados no modo Corte e Vinco". O "cabe em outra máquina" só oferece máquina que faz o modo da caixa: caixa de corte e vinco nunca ganha "cabe na Slotter".
🔁
O que já estava gravado continua valendo: o 300 da Slotter da v889 é lido como o bloco dela e aparece no lugar certo ao abrir.
🔧 Por dentro: js/103-limites-maquina.js (formato { slotter, cortevinco, geral }, jpFuncoesDaMaquina, jpLimitesDoModo, jpLimitesDaMaquina(x, modo), jpAvisosDaRota(…, modo), jpCabeEmOutra(…, modo); o antigo chapa/caixa solto vira geral); js/23-maquinas.js (blocos por modo, ✓ das funções, maqLimitesAtualizarBlocos, maqLerFuncoesDoForm, o Salvar lê só os blocos ativos); js/23-maquinas-fabrica.js (funcoes fixas nas 4). O js/08 não mudou. Teste tests/limites-por-maquina.test.mjs (98 checagens, 17 mutações, todas acusadas). Sem servidor, sem migration, sem Luan.
v2.37.897
🔪 AS LINHAS DA FACA, UMA A UMA. Até agora dá pra dizer o que cada
camada do DXF é — e isso resolve quase toda faca, porque o ArtiosCAD já
sai separado por camada. Mas quando o pré-impressão joga corte e vinco na
mesma camada, não tem palpite que resolva: tem que apontar a linha.
Agora você clica na linha no desenho — quantas quiser, e com Shift o
clique pega a camada inteira daquela linha — e diz o que elas são. O tipo da
linha ganha do tipo da camada, e tem o ↺ voltar tudo pra camada pra desfazer.
📐 O grau da dobra (90°, 45°, 135°, pra dentro ou pra fora) é escolhido no
🧊 Ver e ajustar em 3D, clicando na aba da caixa montada — a tela das linhas
agora diz isso. Essa tela do 3D estava invisível e voltou na v2.37.896.
📦 A ARTE NO PALETE. Você viu certo: a arte inteira estava espremida em meia
caixa. No palete a chapa vai dobrada ao meio, então só metade dela aparece —
e agora essa metade sai no tamanho de verdade. O pacote do palete passou a
parecer a caixa impressa que o cliente recebe. Caixa que vai aberta (corte e
vinco sem acabamento) não dobra: ali a arte continua inteira, como sempre.
⚠️ O ajuste linha a linha vale para aquela faca: se você trocar o arquivo, ele
não é aplicado na faca nova (as linhas estariam em outra ordem e o ajuste cairia
na linha errada, calado). Nada é apagado — ele continua gravado na caixa.
v2.37.896
Você clicava no botão e não acontecia nada. E não era o botão: a tela
abria mesmo — montava a caixa, o aviso "🧊 montando…" aparecia —
só que ficava escondida. Era uma letra fora do lugar dentro da receita de cores da
tela do 3D: a linha que a v2.37.892 acrescentou entrou com o sinal de + na frente em vez
de no fim, e isso fez o navegador jogar fora todo o resto da receita — inclusive a
linha que manda a tela aparecer. Ficaram 2 regras onde deviam existir 25.
⚠️ Não era só esse botão. É a mesma tela do 3D do orçamento, do
Desenvolvimento e da foto do 3D no Plano de Desenvolvimento: desde a v2.37.892 estavam todas
cegas do mesmo jeito. Agora voltaram as quatro.
v2.37.895
🔪 AS LINHAS DA FACA: dizer o que é CORTE, VINCO e PICOTE.
O dono viu o 3D da KININO CX 19 sair desmontado: “onde é picote ele considerou
vinco e ela partiu”.
🔍 O sistema já adivinhava corte/vinco/picote pelo nome da camada e pela cor
(o padrão do ArtiosCAD) — e já guardava o ajuste. Faltavam duas coisas:
uma TELA pra corrigir o palpite, e o picote, que o motor 3D não conhecia.
🔧 Onde fica: Cadastros ▸ Caixas ▸ abrir a caixa ▸
🔪 Linhas da faca (aparece quando a caixa tem faca em DXF). Cada camada do arquivo
vira uma linha da lista com o desenho ao lado, colorido: corte,
vinco, picote e
ignorar (cota, margem, marca de registro).
✅ O PICOTE agora tem as duas respostas:
• destacar marcado → ele corta: a parte de cima sai e vira
caixa de display;
• desmarcado → a linha some: não corta nem dobra, e a caixa
fica inteira. Era aqui que ela partia.
🔄 Salvou, a caixa remonta na hora — é vendo montar que se confere o
ajuste. E o que se salva aqui vale também no mockup do Plano de Desenvolvimento:
é um ajuste só, no cadastro.
🔧 O 🧊 Ver e ajustar em 3D abre NA HORA. Antes ele esperava a arte baixar
antes de aparecer — numa caixa com arte eram segundos de tela parada, e o botão
parecia morto. Agora a tela abre e a arte entra depois, sem desfazer a dobra de quem
já está ajustando.
📝 O motor 3D não mudou: ele só
entende “cor 2 = vinco, o resto corte”. Quem resolve o picote é o módulo
novo, antes dele — uma conversação a menos dentro do motor.
Os ângulos (0 · 45 · 90 · 135 · 180) e a escolha da base
já existiam no 3D, por painel.
v2.37.894
🎨 A ARTE FOI PRO PALETE E PRO 3D — e agora dá pra ARRUMAR o 3D.
Três pedidos do dono vendo o primeiro plano impresso (KININO CX 19).
📦 O palete sai IMPRESSO. A arte vai deitada na tampa dos pacotes —
o pacote é uma pilha de chapas deitadas, e o que se vê por cima é a chapa
impressa. Nas laterais continua o corte do papel, que é o que existe de verdade.
Só a camada de cima recebe: as de baixo ficam tapadas.
🧊 O mockup 3D agora sai com a arte, encaixada pela mesma conta do
orçamento. Sem o encaixe ele sai kraft — nunca com a marca no painel errado,
porque o cliente aprova o que está vendo.
🔧 ONDE SE ARRUMA O 3D (era a pergunta): Cadastros ▸ Caixas ▸ abrir a
caixa ▸ 🧊 Ver e ajustar em 3D. O motor monta tudo em 90° e chuta o painel
maior como fundo — numa maleta isso é um painel do corpo, e a caixa monta
deitada, que foi o que apareceu no papel. Ali você clica em cada aba pra
acertar o ângulo, diz qual painel é o fundo e salva. Ajusta uma vez, vale
pra sempre: fica gravado na caixa e todo plano dali em diante sai assim.
🔑 O ajuste abre com a arte — sem ela você estaria acertando a dobra no
escuro, sem ver se a marca caiu no painel certo.
🔧 Por dentro: a arte é lida uma vez e
serve os três (o layout, o palete e o 3D) — duas leituras dariam duas imagens
diferentes da mesma arte no mesmo papel. E o ajuste sobrevive ao próximo
“Salvar Caixa”: a paletização é reconstruída no salvar e
teria apagado o painel de fundo recém-escolhido.
v2.37.893
📋 O PLANO CHEGOU NO DESENVOLVIMENTO — que é onde o dono pediu primeiro.
As v2.37.891/892 entregaram o documento só pelo cadastro da caixa. Faltava a outra
porta.
🔧 Onde fica: 🏗️ Desenvolvimento ▸ abrir a ficha ▸ no
cabeçalho de cada caixa, o botão 📄, ao lado do ✏️ e do
🗑️.
🔑 O papel é o MESMO — a impressão tem uma
implementação só, e ela passou a aceitar a caixa por id (o
cadastro) ou por objeto (a ficha). Duas portas com dois códigos dariam dois
documentos da mesma caixa.
⚠️ Caixa que ainda não está no cadastro também tem plano:
ele sai com o que a ficha tem — medida, chapa, faca e arte — e as páginas
do pacote e do palete saem “não cadastrado”, porque a paletização
mora no cadastro. A tela avisa que foi assim. Recusar seria pior: o plano da amostra é
justamente o que se manda antes de a caixa existir no cadastro.
🔗 O elo com o cadastro é o caixaId,
nunca o nome; referência + cliente entram só de reserva.
v2.37.892
🖼️ A PLANTA, A ARTE E O 3D ENTRARAM NO PLANO DE DESENVOLVIMENTO.
O papel da v2.37.891 saía com três quadros escritos “sem desenho”. Agora sai completo.
📐 A planta é o mesmo desenho do orçamento — o de corte e
vinco sai do projeto salvo na caixa (poses, encaixe, faca), e a maleta pela mesma fórmula.
Nada foi redesenhado: o motor só ganhou a opção de desenhar num quadro fora da
tela, pra o papel ler dali.
🎨 A arte é a primeira página do PDF que já está no
cadastro da caixa, virada em imagem na resolução do papel.
🧊 O 3D virou FOTO, com a caixa montada e sempre no mesmo
enquadramento — a câmera recua conforme o tamanho da caixa, então toda foto
sai com a mesma folga em volta. Ela é tirada fora da vista: quem estiver girando uma
caixa na tela não perde o que está olhando.
⚡ Medido na bancada: a foto saiu em 0,5 s e passou de 1.578 kB para
111 kB — ela vai deitada sobre branco e em JPEG, porque três imagens de 1,5 MB
deixariam o A4 pesado demais pra imprimir.
⚠️ Desenho que não dá continua saindo “sem desenho” —
nunca um rabisco genérico no lugar. Planta errada no papel é a facaria cortando aço
pela medida errada.
🔧 Por dentro: a janela de impressão nasce
dentro do clique e só depois a arte e o 3D são preparados — depois de um
await o navegador trata a janela como pop-up sem gesto e bloqueia. A conta de onde a
câmera fica virou uma só, usada pela tela e pela foto.
v2.37.891
📄 PLANO DE DESENVOLVIMENTO — o documento em A4 que o cliente recebe.
Pedido do dono em 20/09/2026, com o PDF da CX 16 HABIBS na mão:
“esse é o PDF que eu quero criar dentro do nosso sistema”.
🔍 De 13 blocos daquele papel, o sistema já calculava 10 — espalhados em
quatro telas. A planta, a medida da chapa, a área, o peso, a gramatura, a onda, as
peças por pacote (que já existiam no cadastro) e a paletização
inteira com os três desenhos saem do mesmo motor da seção 8.
➕ O que nasceu agora:
• Esmagamento (FCT) no app da Qualidade — o laudo media coluna, gramatura,
espessura, mullen e umidade, e esse ensaio não existia. Junto veio o
mínimo no cadastro da chapa, pra ter contra o que comparar.
• “O que o cliente pediu” no cadastro da caixa (seção 8):
espessura, tolerância, gramatura, coluna e esmagamento. O sistema sempre guardou o que a
chapa tem; faltava o que o cliente pediu — e é essa
comparação que o documento imprime, com ✓ ou ✗ em cada linha.
• Peso do palete vazio na configuração da paletização.
🔧 Onde fica: Cadastros ▸ Caixas ▸ abrir uma caixa já salva
▸ botão “📄 Plano de desenvolvimento”, no rodapé do
modal. Sai em A4, com a marca da JP.
⚠️ O documento NUNCA inventa número. Campo que a JP não tem sai
escrito “não cadastrado”, e a linha do ensaio fica “—”
quando falta o que o cliente pediu ou o que o laudo mediu — jamais um ✓ de
graça. Antes de imprimir, a tela avisa o que vai sair em branco e você decide.
📝 Os quatro ensaios são tratados como
mínimos (o papel do cliente escreve “Mínima de 350”,
“mínimo de 3,0”); a tolerância da espessura é impressa ao
lado do valor pedido, nunca usada como faixa. Falta ainda a planta desenhada, a
arte e o mockup 3D dentro do papel — o 3D precisa virar foto, e o dono já
pediu pra melhorar o acabamento dele antes.
v2.37.890
🚨 O ORÇAMENTO ABRIA COM A CAIXA DO ORÇAMENTO ANTERIOR.
O dono abriu o orçamento 0017 da PAPELARIA REVAL e o quadro
“adicionar item” estava preenchido com CX ROYAL G · 60.000 caixas
— a caixa da ROYAL PARMA, do orçamento aberto antes.
🔍 A causa: a limpeza do formulário existia em dois lugares copiados
(no fim do “adicionar item” e no “cancelar edição”) — e o
abrir orçamento não tinha nenhum dos dois. Ficavam de pé a referência,
a quantidade, a medida, a chapa, as cores, clichê/faca, a paletização e até
o R$/kg, que é preço.
✅ Agora a limpeza é uma conta só, e as três portas chamam ela.
Ao trocar de orçamento, o quadro volta a ser o da tela recém-aberta —
nenhum campo do orçamento anterior sobra. Entre itens do mesmo orçamento a
quantidade, a chapa e o preço continuam ficando, de propósito: quem lança
10 caixas do mesmo pedido não vai digitar tudo de novo.
🔧 De quebra, o cancelar edição passou a limpar a
paletização — as duas cópias já tinham divergido nisso.
⚠️ Isto é o mesmo defeito da v2.37.888 por
outra porta: lá era o projeto de Corte e Vinco, aqui é o formulário
inteiro. Nenhum orçamento já salvo foi alterado.
v2.37.889
📏
Limites por máquina: cada máquina tem o seu mínimo e o seu máximo, de chapa e de caixa — e a caixa é conferida contra eles no cadastro, no orçamento e na lista. Avisa, nunca barra.
Pedido do dono em
20/09/2026:
"faz o aviso da slotter abaixo de 300 também; no cadastro de máquinas eu coloco os limites de cada máquina, mínimo e máximo, pode ser coladeira e grampeadeira; no orçamento avisar se ficou abaixo ou acima; tem limite de chapa (comprimento e largura) e de caixa (comprimento, largura e altura); a Die Cut tem os dois recursos". Decisões dele: a chapa da maleta conferida é a calculada pelo cadastro; a puxada e a boca do Corte e Vinco viram limite de chapa da Máq. A (puxada = largura, boca = comprimento); o "cabe em outra máquina" entra junto.
🔎
O que era: o sistema só conhecia um limite, o do Corte e Vinco, escondido na configuração do orçamento e usado só pelo desenho da faca. Da Slotter, da Coladeira e da Grampeadeira ele não sabia nada: caixa de 250 de comprimento entrava no roteiro da Slotter sem ninguém avisar.
✅
Onde se configura: Cadastros ▸ ⚙️ Máquinas / Processos ▸ ✏️ de cada máquina ganhou a seção
📏 Limites da máquina (mm):
chapa (comprimento e largura) e
caixa (comprimento, largura e altura internas), cada um com mínimo e máximo. Campo vazio é sem limite. Vale pras 4 de fábrica e pras cadastradas; a Die Cut preenche os dois grupos na mesma máquina. A lista mostra um chip 📏 com o resumo. ↺ Voltar ao padrão de fábrica
preserva os limites.
✅
Cadastro da caixa: abaixo dos chips do roteiro, uma linha por máquina (1ª máquina, meio e fechamento), refeita a cada tecla: ⚠️ vermelho com o número e o limite ("comprimento interno 250 mm abaixo do mínimo 300 mm"), ✅ verde dentro, ℹ️ cinza quando a máquina não tem limites cadastrados. Quando não cabe e existe outra máquina do mesmo tipo em que cabe, diz:
"Cabe na ✂️ Máq. A Corte e Vinco". O Salvar continua livre.
✅
Orçamento: a mesma conferência abaixo de C × L × A,
enquanto se digita, antes de escolher chapa ou quantidade, com as máquinas da rota do item (escolhida ou automática, inclusive as do meio). O item guarda o que ficou fora e a lista de itens mostra o ⚠️. O PDF do cliente não fala nisso.
✅
Lista de Caixas: na coluna Máquina, um selo vermelho curto ("⚠️ C 250 < 300", o texto inteiro ao passar o mouse) quando a caixa não cabe na máquina do roteiro dela; o resumo da busca por medida ganha "⚠️ N fora do limite da máquina". A pergunta de hoje vira: 📐
<300 e olhar os selos.
🔁
O Corte e Vinco: a puxada 300–950 e a boca 2.200 da configuração do orçamento passam a ser
reserva: valem enquanto a Máq. A não tiver limite de chapa no cadastro; o 🎨 desenho real da faca lê primeiro o cadastro da máquina. A seção antiga da configuração continua lá, dizendo onde os limites moram agora.
🔧 Por dentro: arquivo novo js/103-limites-maquina.js (régua pura: jpLimitesNormalizar, jpConferirLimites, jpLimitesDaMaquina, jpAvisosDaRota, jpCabeEmOutra; telas: cxLimitesRender, orcLimitesTela, jpLimitesSeloDaCaixa). Os limites moram no snapshot maquinas_processos (fábrica: fabrica[chave].limites; cadastradas: m.limites) — js/23-maquinas-fabrica.js expõe e normaliza, js/23-maquinas.js tem a seção do modal e o chip. O js/08 só ganhou chamadas (cxRotRender, cxAplicarChapa, o começo do orcRecalcItem, o item e a lista de itens, a célula da lista de Caixas) e duas divs. js/102 conta os fora do limite; js/23e lê a máquina antes da reserva. Teste tests/limites-por-maquina.test.mjs (77 checagens, 14 mutações, todas acusadas); o teste antigo limites-maquina-cv continua verde. Sem servidor, sem migration, sem Luan.
v2.37.888
🚨 UM ORÇAMENTO HERDAVA O PROJETO DE CORTE E VINCO DO ORÇAMENTO ANTERIOR.
O dono abriu o orçamento da REVAL e viu, no palete, a faca da DCX.
🔍 A causa: o projeto de C&V da tela vive em quatro variáveis, e o
abrir orçamento zerava sete outras coisas e nenhuma dessas quatro. Quem
projetasse (ou puxasse) uma caixa num orçamento e abrisse outro em seguida levava o projeto
junto, calado.
💰 E o estrago passava LONGE do desenho. O nº de poses do projeto divide o
peso da caixa, e peso × R$/kg é o PREÇO: um projeto vazado de 2 poses
cortava o preço pela metade. Pior: ao adicionar o item, o projeto da outra caixa
era GRAVADO dentro dele. O desenho da faca no palete (v2.37.887) só tornou isso
visível — o problema era anterior.
✅ Agora: abrir um orçamento começa com o Corte e Vinco limpo. Quem já tem
projeto salvo no item continua vendo o dele normalmente — ele é recarregado ao abrir a caixa
pra editar.
⚠️ Se você viu um orçamento de corte e vinco com a faca errada, confira o
preço dele — pode ter sido orçado pela metade. O sistema não mexe em orçamento
já salvo; essa conferência é sua.
🔧 Por dentro: orcCvZerar() (js/08) — a mesma linha estava escrita à mão em
duas portas e faltava na terceira (abrirModalOrcamento); virou uma função
só, e o teste falha se alguém escrever uma 4ª cópia. 16 checagens e 4 mutações em
tests/orcamento-nao-herda-projeto-cv.test.mjs. Sem servidor, sem Luan.
v2.37.887
🛠 O PALETE DO ORÇAMENTO PASSOU A SAIR COM O RECORTE DO DXF — a silhueta real da
faca no lugar do tijolo, igual à seção 8 · Paletização do cadastro. Pedido do dono:
"quero que usa o DXF igual no cadastro de caixa", e logo depois "com todas as caixas".
📦 De onde sai o DXF, nesta ordem: (1) o projeto feito agora na tela
🎨 Projetar Corte e Vinco; (2) a caixa já cadastrada escolhida no item — que é o
caso mais comum. O projeto da tela ganha porque é a decisão mais nova. Caixa sem DXF continua
saindo como retângulo, calada.
✅ Nenhum número muda por causa disso, e isso foi MEDIDO nas três facas de verdade
(PARMEGIANE P, MITTO 06 e BANDEJA F0427): lastro, camadas e caixas por palete saem idênticos
com e sem o recorte. O motor só usa o desenho pra desenhar.
⚠️ O DXF é o DA CAIXA DO ITEM, nunca o que está aberto na tela do Corte e Vinco —
de lá ele desenharia a faca de OUTRA caixa, calado. E quando o contorno da faca não fecha
(acontece: a BANDEJA F0427 é uma), o desenho cai no retângulo e diz isso na legenda, em vez
de quebrar.
⏱️ Interpretar o DXF custa de 3,5 a 11,6 ms (145 KB no MITTO 06) e este painel roda
a cada tecla — então o resultado fica guardado: da segunda leitura em diante são
0,001 ms.
🐛 E o teste pegou um defeito no caminho: anexar o DXF não redesenhava o palete.
Como o recorte não muda lastro nem camadas, a tela achava que nada tinha mudado e ficava com o
tijolo. Consertado.
🔧 Por dentro: cvContornoDoDxf novo no js/23c (puro, com memória de
uma vaga, e sem encostar no DXF da tela) — a volta do contorno virou uma função só
(_cvContornoDeCamadas), usada por ele e pelo cvDxfContorno de sempre;
_orcDxfDoItem + dxfGeo no _orcMedidasPraPalete (js/08) e no
_jpPalLastroAuto (js/72). 45 checagens e 11 mutações em
tests/orcamento-ver-o-palete.test.mjs. Sem servidor, sem Luan.
v2.37.886
🔒
Estoque PA: o doc só grava por merge (passo 2 da proteção). 🧰
Precisa do Luan: pm2 restart all — o mesmo restart da 884 cobre as duas, sem migration.
Pedido do dono em
20/09/2026:
"pode fazer o passo 2 tbm, o SO_MERGE". O salvar-inteiro do doc
estoque era o "quem salva por último ganha" (§9.6, pendente desde a v2.37.572): uma tela em versão velha devolveu 7 MB de sujeira por cima da faxina duas vezes hoje. Agora a API
recusa o salvar-inteiro (409) e só aceita o merge, registro a registro — como já é com romaneios e saídas de palete. O PC continua tentando o salvar antigo e leva o 409 em silêncio (só no console); nenhuma tela sente.
O que teve que mudar junto: o merge funde e
nunca apaga chave. O único "apagar" que o estoque fazia era
desfazer um ✕ dado por engano (o ↩️ estorno, v2.37.585) — e isso só chegava ao servidor pelo salvar-inteiro. Agora o desfazer é
marca também (
desfeitoEm, com quem e quando), que viaja pelo merge e deixa o rastro dos dois lados. Um ✕ novo depois do desfazer vale de novo. Na chegada do doc fica, por pedido, a versão com o acontecimento mais novo — senão um poll que chega logo depois do estorno traria a marca velha de volta.
O que congela: o array antigo de linhas e o livro antigo ficam como estão no servidor; quem manda é o mapa por id (lápide tira, keyed manda), e a leitura das telas e dos apps é a mesma de antes.
🔧 Por dentro: api/src/routes/snapshots.js (SO_MERGE += estoque) · js/03-estoque.js (_estMarcaAtiva — a pergunta "está marcado?" num lugar só, lida pelos 4 leitores; _estDesfazerMarca no estorno; _estFundirMarcas na chegada). Teste tests/estoque-so-merge.test.mjs (34 checagens, 7 mutações); 9 harnesses antigos ganharam os ajudantes e os dois que afirmavam "a marca é apagada" passaram a afirmar "a marca fica desfeita". (Nasceu 885; o número já estava em outra frente.)
v2.37.885
📐
"<300" na busca por medida + a coluna Máquina na lista de Caixas.
Dono,
20/09/2026:
"o limite da máquina é de 300, quero saber quais estão abaixo disso" →
"é o comprimento interno na Slotter, pode fazer o <300" →
"quero saber qual máquina está cadastrada também, não sei se é corte e vinco ou slotter".
🔎
O que era: a busca da v2.37.881 achava caixa
perto de uma medida (± mm). "Menor que 300" não tinha como perguntar, e a lista não dizia em que máquina a caixa roda.
✅
Agora o campo 📐 aceita sinal: <300 (menor que),
<=300,
>300 e
>=300, por medida e
sem tolerância — 300 não é menor que 300 nem com ± 50. Dá pra misturar:
<300x200 = comprimento abaixo de 300 e largura perto de 200; a tolerância vale só pra medida sem sinal, e o recorte do relatório diz isso. O campo 📄 Chapa aceita os mesmos sinais.
✅
A tabela de Caixas ganhou a coluna "Máquina": a 1ª máquina do roteiro cadastrada na caixa (Máq. B Slotter, Máq. A Corte e Vinco…), ou
"sem máquina" quando não tem. O resumo da busca diz de que máquina são:
"3 caixas de 3 clientes: ALPACK 1 · KININO 1 · TANGARA 1 · 🏭 Máq. A Corte e Vinco 1 · Máq. B Slotter 1 · sem máquina 1". As parecidas do orçamento também mostram a máquina de cada caixa.
ℹ️ A pergunta do dono vira: Cadastros → Caixas, 📐
<300 — a linha de cima responde quantas, de quem e de que máquina; as da Slotter são as que não rodam.
🔧 Por dentro: js/102-caixa-por-medida.js (jpMedidaTexto devolve ops, cabeNoSinal, jpMaquinaDaCaixa lê o maqCorte, textoMaquinas no resumo); no js/08 só a célula da máquina no renderCaixas e o colspan 13; no sistema.html a coluna e a dica no campo. O relatório impresso/PDF continua sem a coluna. Teste tests/caixa-por-medida.test.mjs (88 checagens, 14 mutações, todas acusadas). Sem servidor, sem migration, sem Luan.
v2.37.884
🛡️
Estoque PA: o servidor passa a limpar o doc em toda gravação. 🧰
Precisa do Luan: pm2 restart all (sem migration). Até o restart, nada muda — a régua nos PCs continua valendo.
Pedido do dono em
20/09/2026:
"pode preparar a proteção no servidor pro Luan". O motivo: a faxina das lápides e do livro (878/880) foi
desfeita duas vezes, 21 e 88 segundos depois, por uma tela do sistema que ainda estava numa versão antiga — ela guardava o mapa inteiro em memória e o mandava de volta ao salvar. A régua no PC só vale nos PCs atualizados, e o sistema aberto não recarrega sozinho (só mostra a faixa "Atualizar"). Agora a
mesma régua roda no único lugar por onde todo aparelho passa: a API, antes de gravar o doc
estoque — tanto no salvar inteiro quanto no merge. Um aparelho velho pode mandar 7 MB de sujeira: o servidor guarda 0,2 MB.
O que muda: nada na tela. A régua é a mesma dos PCs (lápide velha sem linha no array sai; entrada automática idêntica no mesmo dia vale uma) e o dia é contado no relógio da
fábrica (o servidor roda em UTC e às 22h de Rio Preto já é amanhã em Londres). A régua não foi copiada pra API: ela
lê o mesmo arquivo que os PCs usam. Se o arquivo faltar ou der erro, o servidor grava como veio e avisa no log — a proteção nunca é motivo de a fábrica não conseguir salvar.
O que NÃO entrou (passo 2, se o dono quiser): recusar de vez o salvar-inteiro do doc (
estoque no
SO_MERGE) e deixar só o merge, como já é com romaneios e saídas de palete. É a cura da raiz do "quem salva por último ganha", mas é outra mudança e vai sozinha.
🔧 Por dentro: api/src/lib/estoque-pa.js (novo — carrega o js/81-estoque-pa.js real num sandbox e expõe compactarEstoque(dados), fail-open) · api/src/routes/snapshots.js (_gravarSnapshot e o /merge chamam a compactação só pra estoque) · js/81 (compactarLivro aceita {fuso}; o navegador não passa nada). Teste tests/api-estoque-compacta-no-write.test.mjs (30 checagens, 7 mutações; roda o PUT e o merge reais contra um banco de mentira, com o relógio em UTC).
v2.37.883
🖼️ DÁ PRA VER O PALETE DESENHADO DENTRO DO ORÇAMENTO — os mesmos três
quadros da seção 8 · Paletização do cadastro da caixa: vista de cima (com as abas
camada ímpar / camada par), perspectiva da 1ª camada e perspectiva do palete completo,
com as mesmas legendas.
🎯 É o MESMO motor, não um parecido. São os mesmos quatro desenhistas do cadastro
recebendo a mesma conta — conferido no teste byte a byte contra o que a seção 8 produz.
Dois desenhos próprios divergiriam na primeira correção, e aqui a correção é sempre sobre
papelão de verdade.
👆 Fica atrás de um clique (🖼️ Ver o palete, dentro do bloco de Paletização),
como o dono pediu — e há um motivo a mais: medido, os três desenhos custam 140 KB de
HTML por vez, e esse painel é refeito a cada tecla das medidas. Fechado, não custa
nada. Aberto, só redesenha quando o palete muda: mexer na quantidade não refaz os 128 KB
do palete completo.
✅ No cabeçalho do bloco já aparece o resumo (4 × 30 = 3.000 cx) sem precisar abrir. Sem
medida, o quadro diz o que falta em vez de desenhar um palete de mentira; e as abas
ímpar/par só aparecem quando a amarração realmente gira a camada par — em arranjo
simétrico as duas seriam o mesmo desenho.
🔧 Por dentro: _orcPalDesenhar + _orcPalAssinatura +
orcPalDesenhoAbrir/orcPalDesCamada (js/08), chamando
palSvgTop/palSvgIso/palCapTop/palCapCompleto do
js/19-paletizacao.js com o resultado cru do palCalcular. Sem o js/19 na
página o bloco some em vez de abrir vazio. 26 checagens e 6 mutações em
tests/orcamento-ver-o-palete.test.mjs. Sem servidor, sem Luan.
v2.37.882
⚙️
As 4 máquinas de fábrica deixaram de ser trancadas. Pedido do dono em
20/09/2026:
"não quero deixar a máquina de fábrica presa assim, quero poder editar elas porque o sistema vai ser para várias empresas".
Em
Cadastros ▸ ⚙️ Máquinas / Processos a Máq. B Slotter, a Máq. A Corte e Vinco, a Coladeira 01 e a Grampeadeira 01 viraram linhas iguais às outras: ✏️ muda
nome, ícone e velocidade padrão; ⏸
pausa a máquina que aquela empresa não tem (ela some das listas, o histórico fica); ↺
volta ao padrão de fábrica. Sumiram o selo "DE FÁBRICA" e o "chave do sistema".
O que fica: a
chave (
impressora,
coladeira…) e a
posição no fluxo — é como o sistema reconhece a etapa por dentro (sensor, turno, cronograma, roteiro). Por isso elas não têm 🗑; a janela explica.
📍
Onde o nome e o ícone novos aparecem: a lista da 1ª máquina do
pedido, o cadastro da
caixa, os quadradinhos e a lista do cadastro de
operadores, a sugestão do
registro de produção, os painéis de
Velocidades, o
Mural, o
Custo-hora, a
Manutenção, o
cronograma e o
Planejamento (esses dois só quando a máquina foi renomeada — sem mexer, ficam SLOTTER/COLADEIRA de sempre), a Produtividade, a Logística e o
app do operador (chips do login, cabeçalho, abas e cartão do pedido). Máquina pausada some dessas listas; pedido que já estava nela fica marcado
"⏸ pausada no cadastro" e a carteira avisa que ninguém vê.
🖨️
"Deixa os ícones todos iguais para todas impressoras" (dono, 20/09): no app do operador o ícone agora vem do
tipo da máquina no cadastro — a
Maq. C Die Cut aparecia com chave inglesa e agora é impressora como as outras; máquina cadastrada de fechamento aparece como caixa. E onde antes tinha 🅱️/🅰️/📌 escrito no código (pedido, caixa, operadores, produtividade, logística) agora aparece o ícone do cadastro (🖨️ ✂️ 📦 🔗) —
"tudo relacionado a máquina deixa tudo igual".
🔒
O que NÃO muda: o que se grava. Pedido, operador e apontamento continuam gravando "Máq. B Slotter", "Máq. A Corte e Vinco", "Coladeira", "Grampeadeira" — é a identidade que o tablet casa com o pedido (§9.7). Renomear muda só o que a pessoa vê, e o nome velho gravado continua caindo na máquina certa (Mural, velocidades, turno, sensor).
🔧 Por dentro: js/23-maquinas-fabrica.js (novo, compartilhado com o tablet: quem são as 4, como se chamam hoje, maqFabricaAcha exato por slug), js/23-maquinas.js (a tela; o ajuste em maquinas_processos.fabrica[chave], só o que difere do padrão), js/01 (maqCorteOpcoes, maqCortePadrao, canon, etapa do registro, velocidade única 3b, jpMaquinaExibir/jpMaquinaChipHtml), js/06, js/08, js/05, js/09, js/21 (cronNomesFabrica, cronLanesVisiveis), js/83, js/38, js/49, js/61, painel_operador.html (_maqNomeOp, maqInfo por tipo, carregarMaqProc no boot). Teste tests/maquinas-fabrica-editaveis.test.mjs (202 checagens, 19 mutações acusadas). Sem migration e sem pm2 restart — é tudo tela. CLAUDE.md §18.
v2.37.881
📐
Achar caixa pela MEDIDA (aproximada) — na lista de Caixas e no orçamento.
Pedido do dono em
20/09/2026:
"quero saber todas as caixas maletas que tem 300x no comprimento e quais cliente tem" →
"cria uma porta para localizar caixa pelo comprimento, largura e altura, aproximadas, e pela chapa também" →
"na lista de caixas e no orçamento, e põe o botão usar chapa".
🔎
O que era: a lista de Caixas só achava por código, cliente e faca/clichê. Pra saber quem tem caixa de 300 de comprimento era abrir caixa por caixa.
✅
Agora, em Cadastros → Caixas: dois campos novos ao lado da busca —
📐 Medida interna (digite
300x200x150,
300x200 ou só
300) e
📄 Chapa (
1992x602 ou só
1992) — e a
tolerância (± 10 mm por padrão; medida exata, 5, 20 ou 50). Medida que você não digitou não filtra. A tabela sai da mais próxima pra mais longe e, em cima, a resposta:
"12 caixas de 7 clientes: DEUSA 3 · KININO 2 · …". Inativa continua marcada; o relatório impresso e o PDF saem com o mesmo recorte e dizem qual foi.
✅
No orçamento: embaixo de C × L × A do item aparece
"📐 Parecidas no cadastro (± 10 mm)" com até 6 caixas — cliente, código, medida, chapa, onda, faca e clichê; ⭐ as do cliente deste orçamento vêm primeiro, as dos outros depois (é isso que responde "quem tem"). Sobrando, "+N". Aparece enquanto você digita, antes de escolher chapa. No corte e vinco com a chapa digitada, a busca é pela chapa.
"abrir" abre a caixa no cadastro;
"usar chapa" (só no corte e vinco) escreve a chapa C × L no item
e mais nada — preço, R$/kg, clichê e arte de outro cliente nunca entram (a régua da v2.37.8xx). Caixa inativa fica fora das parecidas.
⚠️ Não é a "📐 caixa parecida" da v2.37.696, que escolhe UMA caixa com velocidade pra emprestar o ritmo — as duas convivem no mesmo item.
🔧 Por dentro: arquivo novo js/102-caixa-por-medida.js (jpMedidaTexto, jpCaixasPorMedida e jpResumoPorCliente são funções puras; cxMedidaFiltrar/cxMedidaResumoTela/cxMedidaRecorteTexto na lista, orcParecidasTela/orcUsarChapaParecida/orcAbrirParecida no item). O js/08 só ganhou as chamadas (cxListaNaTela, renderCaixas, cxRelatorioRecorte, o COMEÇO do orcRecalcItem e a limpeza no "limpar campos do item"). Teste tests/caixa-por-medida.test.mjs (64 checagens, 11 mutações, todas acusadas). Sem servidor, sem migration, sem Luan.
v2.37.880
📖
Estoque PA: a faxina do livro de movimentos.
Pedido do dono em
20/09/2026, logo depois das lápides:
"pode fazer a faxina do livro de movimentos tbm, com backup". O que havia (cópia das 13:38):
8.214 movimentos, 8.123 deles "entrada" — e
7.297 eram a MESMA frase ("2 palete(s) no PA · Pedido 24178", 590 cx da GAIOTO) escrita uma vez por poll durante três dias, pela porta automática que repõe linha no PA enquanto o cache vazio criava cópia (o buraco fechado na 877). O estoque não entrou 7.297 vezes.
A régua: entrada
automática idêntica (mesma origem, item, quantidade e frase)
no mesmo dia vale uma, a primeira — a que fica diz que a linha voltou naquele dia, então o retrato fica (a GAIOTO fica com 15, 16, 17 e 18/09).
Todo o resto do livro não é tocado: Finalização produção, Expedição, Saída por palete, ajustes, Remoção manual, Entrada manual, recálculos — os 320 movimentos reais saem 320. Na cópia das 13:38:
8.214 → 405 movimentos, 1.880 KB → 90 KB.
A régua roda nos mesmos dois pontos da faxina das lápides (quando o doc chega do servidor e antes de cada salvar), porque cada PC guarda o livro inteiro em memória e o devolve ao servidor ao salvar — foi isso que se viu às 13:38:57 de hoje: 21 segundos depois da limpeza das lápides no servidor, um PC ainda na versão anterior salvou e devolveu as 7.362.
A limpeza no servidor é refeita com esta versão no ar em todos os PCs, com backup antes em
~/backups-jp/.
🔧 Por dentro: js/81-estoque-pa.js — JPEstoquePA.compactarLivro(movimentos, {origens}) e ORIGENS_AUTOMATICAS (as duas frases da porta _estCriarLinhaFaltante). js/03-estoque.js — _estCompactarLivro + _estMapaDoLivro no setDados do servidor e na guarda do PUT (mapa e array). Sem o js/81 na página, nada muda. Teste tests/estoque-faxina-livro.test.mjs (28 checagens, 9 mutações; mede o doc real quando a cópia está em ~/backups-jp). Sem servidor, sem Luan.
v2.37.878
🧹
Estoque PA: a faxina das lápides.
Pedido do dono em
20/09/2026:
"pode fazer a faxina das lápides tbm, com backup antes". O que havia (medido no servidor às 13:27): o doc do estoque com
7,3 MB —
7.371 chaves no mapa por id pra
9 linhas vivas;
7.362 eram lápides (a marca de "esta linha saiu"), 7.329 delas de
cópia da mesma linha (a cópia que o PC criava a cada poll com o cache vazio — o buraco fechado ontem na 877),
nenhuma escondendo linha nenhuma (o array legado tinha 8 linhas, todas vivas) e 2.448 carregando os paletes inteiros de um único pedido (1,75 MB de peso morto). Cada PC ainda guardava esse mapa todo em memória e o mandava de volta a cada salvar: limpar só o servidor não adiantaria.
O que muda: uma lápide só serve pra esconder um id que o array legado ainda traz. Lápide de id que o array
não tem e com mais de
2 dias não protege nada e
sai; a que fica, fica
enxuta (só id, pedido, cliente, código, quando, quem e o motivo).
Linha viva não é tocada, e lápide sem data legível fica (dúvida não apaga). A régua roda quando o doc chega do servidor e antes de cada salvar, então o mapa não volta a inchar.
O que NÃO muda: o
livro de movimentos fica inteiro (8.214 lançamentos, 2,1 MB) — ele é o retrato do que aconteceu, inclusive das cópias; mexer nele é outra decisão.
Backup antes em
~/backups-jp/estoque-antes-faxina-2026-09-20-13-27.json; as lápides tiradas do servidor ficam guardadas em arquivo próprio na mesma pasta. Na cópia de 13:27 a régua deixa o mapa em
18 chaves e 15 KB.
🔧 Por dentro: js/81-estoque-pa.js — JPEstoquePA.compactarLapides(porId, lista, {agora, prazoMs}) (dono único da régua; PRAZO_LAPIDE_MS = 2 dias). js/03-estoque.js — _estCompactarLapides chamado no setDados do servidor e na guarda do PUT (estGuardaSalvar, no mapa fundido servidor ∪ aparelho). Sem o js/81 na página, nada muda. Teste tests/estoque-faxina-lapides.test.mjs (28 checagens, 7 mutações; mede o doc real quando a cópia está por perto). Sem servidor, sem Luan.
v2.37.877
🔁
Estoque PA: acabou o vai-e-volta da linha do pedido ENTREGUE.
Pedido do dono em
20/09/2026:
"conserta o vai e volta tbm". O que estava acontecendo (medido no livro de movimentos do servidor): a porta que
remove do PA tirava a linha do pedido entregue, e a porta que
cria ("Lote novo depois de uma carga") devolvia a mesma linha no poll seguinte, porque só perguntava "sobrou palete que o livro não viu sair?" e
nunca olhava o status do pedido. FK 19403 e TANGARA 03 FLOPS 46:
13 entradas cada um em dois minutos.
O que muda: quem cria a linha passou a fazer
a mesma pergunta de quem remove — pedido
carregado ou
entregue não ganha linha nova no PA (o "carregado parcial" continua ganhando, que é justamente o pedido com palete no galpão). E a reconciliação
não cria nada antes de o estoque ter chegado do servidor: era o PC lendo a cópia velha do cache que recriou 3 cópias e desfez 3 ✕ do dono às 09:27.
O que NÃO muda: a entrega parcelada de verdade (pedido pronto p/ carregar, saiu metade dos paletes) continua voltando pro PA sozinha, como desde a v2.37.561. Nada foi apagado: o doc continua com as 7.354 lápides e os 8.244 movimentos — limpar isso é outra conversa, com backup antes. As linhas que já estão lá hoje somem sozinhas no próximo poll (a porta que remove continua igual) e não voltam mais.
🔧 Por dentro: js/03-estoque.js — _estCriarLinhaFaltante pergunta _estStatusDeSaida(pid) (a régua do removerExpedidasDoEstoque) e _estDocChegou() (o setDados do servidor carimba STATE_EST.doServidorEm; o boot do cache não). Vale também pro ↩️ estorno. Teste novo tests/estoque-ping-pong-entregue.test.mjs (23 checagens, 6 mutações, e contra a versão anterior ele reproduz o vai-e-volta). Sem servidor, sem Luan.
v2.37.876
🚚
O app do motorista deixou de mostrar o "📦 Ver estoque da fábrica".
Pedido do dono em
20/09/2026:
"pode tirar o estoque no app do motorista, acho que não tem necessidade de saber o que tem na fábrica".
O botão e a tela (que entraram na v2.37.807 pra todos os apps) saíram só dali — operador, encarregado, onduladeira, vendedor e qualidade continuam com a mesma tela e a mesma conta do PCP.
🔍
E por que a lista do app estava diferente da do PCP naquela hora (as duas fotos do dono): não era conta diferente, era
relógio. O app leu o estoque às
09:26 com 9 linhas. Às
09:27 o PC do PCP recriou seis linhas pela porta "Lote novo depois de uma carga": três eram
cópias de linhas que já existiam (DCX PARMEGIANE G, JESSE CX 05 ASSADO, EMPORIO PRIME) e três eram as linhas que o dono tinha tirado com o ✕ em 27/08 (TANGARA 05 FLOPS 92, FK 19403, TANGARA 03 FLOPS 46).
Duas dessas, FK 19403 e TANGARA 03 FLOPS 46, estão
entregues — e aí a porta que remove ("pedido entregue sai do PA") e a porta que cria ("sobrou palete no livro") se revezaram a cada poll:
13 entradas cada uma em dois minutos, gravadas no livro de movimentos. O doc do estoque está com
5,2 MB, 7.354 lápides e 8.244 movimentos.
Isso ainda não está consertado — está anotado pra próxima frente; nada foi apagado.
🔧 Por dentro: painel_motorista.html (sem js/81, js/82 e o botão). Teste tests/estoque-geral-em-todo-app.test.mjs (o motorista passou pra guarda inversa). Sem servidor, sem Luan.
v2.37.875
⚙️
Botão "N sem máquina": o número agora segue a busca e o período da tela — é exatamente o que o clique vai mostrar.
Pedido do dono em
19/09/2026:
"faz o número do botão seguir o filtro também".
🔍
O que era: o botão contava a carteira inteira e a tabela respeitava a busca e o período: "12" em cima com 3 linhas embaixo.
✅
Agora: a conta é a MESMA da tabela, com a busca e o período que estão na tela. O filtro de status fica de fora de propósito: é ele que o clique troca — se entrasse, "Programado" diria 3 e o clique mostraria 8. Sem busca e sem período, continua sendo a carteira inteira. O título do botão (passe o mouse) diz de onde vem o número.
🔧 Por dentro: js/01-core.js (pcpContarSemMaquina passa a usar a pedidosFiltrados da tabela com o grupo g_sem_maquina — uma régua só, §9.13). Teste tests/botao-pedidos-sem-maquina.test.mjs (78 checagens, 9 mutações; bloco ⑨ busca "tangara"/"vivimar"/"deusa", período 7 dias e personalizado, e o status ficando de fora). Sem servidor, sem Luan.
v2.37.874
⚙️
Botão "N sem máquina": pedido PRONTO e pedido BLOQUEADO NO FINANCEIRO não contam mais.
Decisão do dono em
19/09/2026, vendo o botão no ar:
"pronto e bloqueado financeiro não conta".
🔍
O que era: a conta do botão era idêntica à do 📆 Planejamento, e lá um pedido pronto (produção terminada) ou bloqueado no financeiro, sem máquina no cadastro, entra no quadro "Falta o que o plano precisa saber". No botão isso virava número pra resolver, sem ter o que resolver agora.
✅
Agora: o botão conta só pedido aberto, com produção a fazer, que não esteja pronto nem bloqueado no financeiro. O Planejamento continua listando os dois (ele planeja capacidade, e o bloqueado vai precisar de máquina quando destravar) — essa é a única diferença entre as duas contas, e o teste a mantém escrita.
🔧 Por dentro: js/83-planejamento-semanal.js (pedidoSemMaquina: dois status a mais ficam fora). Teste tests/botao-pedidos-sem-maquina.test.mjs (65 checagens, 8 mutações — a nova apaga a decisão e o teste fica vermelho). Sem servidor, sem Luan.
v2.37.873
⚙️
Carteira do PCP: um botão diz quantos pedidos estão sem máquina — e o clique mostra só eles.
Pedido do dono em
18/09/2026:
"quero um botão que mostre quantos pedidos estão sem máquina".
🔍
O que era: a conta já existia, mas só na aba 📆 Planejamento (quadro "Falta o que o plano precisa saber"). Na Carteira, que é onde o pedido se resolve, ninguém via o número — e pedido sem máquina não entra na conta de capacidade nem chega no tablet certo.
✅
Agora: na barra de filtros da Carteira do PCP, ao lado dos seletores, o botão
"⚙️ N sem máquina" (âmbar quando tem algum; com zero ele fica ali, discreto).
Clique = a tabela mostra só esses pedidos (o seletor de status ganhou a opção "⚙️ Sem máquina"); clique de novo ou "Apenas ativos" = volta ao normal. Daí é abrir cada um e escolher a máquina.
📏
O número é o MESMO do Planejamento, de propósito: pedido aberto, com produção a fazer, cuja etapa de corte não tem máquina nem no pedido nem no cadastro da caixa. A pergunta saiu de dentro do Planejamento para uma função só, que as duas telas usam — duas contas da mesma coisa divergem sozinhas (foi assim com o Estoque PA em duas telas, v2.37.804).
⚠️ O botão não escolhe máquina e não mexe no cronograma: só conta e filtra. Se a conta do Planejamento ainda não carregou, ele fica sem número em vez de inventar zero.
🔧 Por dentro: js/83-planejamento-semanal.js (pedidoSemMaquina → window.jpPedidoSemMaquina; etapasQueFaltam passa a perguntar a ela), js/01-core.js (grupo g_sem_maquina em pedidosFiltrados, pcpContarSemMaquina, pcpAtualizarBotaoSemMaquina, pcpFiltrarSemMaquina), sistema.html (botão + opção) e css/main.css. Teste tests/botao-pedidos-sem-maquina.test.mjs (60 checagens, 7 mutações). Medição na carteira real fica pra próxima abertura do sistema: o próprio botão mostra o número. Sem servidor, sem Luan.
v2.37.872
📄
App da Expedição: o romaneio agora sai também pelo 📜 Histórico de cargas — reenviar a 2ª via (mesmo número, mesma data) ou emitir o que ficou sem. E a tela não fica mais presa em "⏳ Preparando…".
Pedido do dono em
17/09/2026:
"quando eu vou imprimir o romaneio ele abre uma tela pra depois abrir… no app do expedidor como se ficasse em loop; agora o app não conclui o romaneio e, fechando o expedidor, não consegui emitir de novo. Quero que no histórico de carga eu consiga reenviar o romaneio — não editar, somente reimprimir."
🔍
O que era: o PDF do romaneio só existia na tela "Carga Finalizada". Saiu dela (fechou o app, atualizou, tocou em Nova Carga), acabou — a carga estava no Histórico, o número estava gravado no servidor (medido no mesmo dia:
toda carga fechada tinha romaneio registrado, inclusive a das 15:33, Nº 94) e não havia porta nenhuma pra reenviar.
E o app não tinha teto de tempo em ida nenhuma ao servidor: no engasgo do servidor (medido: o MESMO pedido de dados levou
30 s+ numa hora e
0,3 s minutos depois) a tela ficava em "⏳ Preparando…" pra sempre, sem botão nenhum.
✅
Agora, no app:
📜
Histórico (Por carga e Por motorista): cada carga fechada ganha o botão
📄 —
"Reenviar romaneio Nº 94" quando já tem papel valendo (2ª via:
mesmo número, mesma data, itens como foram gravados; só o que está vazio é completado pelo cadastro), ou
"Romaneio — ainda não emitido" (aí emite pelo mesmo caminho da tela de sucesso).
Nunca edita, nunca cancela, nunca dá número novo pra carga que já tem papel valendo — substituir romaneio continua sendo do sistema.
⏱
Teto de tempo: 25 s pra falar com o servidor, 60 s pro PDF. Passou, a tela diz o que demorou e oferece
🔁 Tentar de novo — se já tiver gravado, sai o mesmo número.
📎
Compartilhar entrega SÓ o arquivo PDF — em qualquer caminho (WhatsApp, e-mail, salvar). Antes ia título e texto junto do arquivo, e o WhatsApp do iPhone entregava o texto e deixava o PDF pra trás.
✅ Depois de compartilhar, o botão diz
"✅ enviado HH:MM" — a folha de compartilhar abria e fechava sem nada mudar na tela, e parecia loop.
🚨
Cancelado não conta mais como "já tem romaneio" no app (a regra do sistema desde a v2.37.740): carga cujo papel foi cancelado no PC não reusa o número cancelado. O cancelado aparece riscado com o motivo na janela — nada some.
🔧 Por dentro: painel_expedicao.html (_romComTeto, _romDocDoServidor, romHistAbrir, _romPrepararSegundaVia, _romItensSalvosCompletos, ROM_PRONTOS marcado por carga, janela #modal-rom-hist).
Teste tests/romaneio-2a-via-no-app.test.mjs (63 checagens, 12 mutações — contra a versão do ar ele reproduz o defeito). Sem servidor, sem Luan.
v2.37.870
🌫️
3D: sombra esfumaçada, a caixa em pé sobre o fundo (e a base escolhida no Desenvolvimento vale sempre), e papel kraft com textura.
Pedido do dono em
16/09/2026, vendo a caixa girar:
"deixa essa sombra mais suavizada, esfumaçada — eu estava pensando que era um pedaço de caixa";
"a caixa está ao contrário: LADO escrito de baixo pra cima, a base está na lateral. O correto é a base embaixo. Lá no Desenvolvimento eu escolhi qual é a base pra que ela já venha";
"quero uma textura de papel kraft como padrão".
🌫️
Sombra: o sol ficou mais a pino (a sombra comprida era o "pedaço de caixa"), a sombra projetada ganhou desfoque e o chão pega mais leve; a mancha embaixo da caixa ficou maior e mais suave.
📦
Base: o motor chutava o painel maior — na maleta é um painel do CORPO, e a caixa montava deitada de lado. Agora a maleta do orçamento monta sobre a
maior aba de baixo (o fundo), em pé.
E no
Desenvolvimento a base escolhida na janela passa a ser
salva junto com as dobras (botão "Salvar dobras e base") e volta sempre que a caixa abre — antes só as dobras ficavam.
📄
Kraft: os painéis ganharam textura de papel kraft (polpa manchada, fibras e grão), gerada na hora — não depende de internet nem de arquivo, o app abre sem sinal, e não tem licença de foto.
A arte é
impressa sobre essa textura (o branco da arte vira papel, como na máquina). No papel branco a arte fica como está.
🔧 Por dentro: js/70-caixa3d.js (VSM + shadow.radius, kraftTex, aplicarPapelNaArte, o.base, SALVAR(dobras, base)),
js/34 (dados.base3d por merge, sem migration), js/101 (orcMaletaBase). Testes tests/caixa3d-camera-e-papel.test.mjs e tests/arte-na-faca-orcamento.test.mjs. Sem servidor, sem Luan.
v2.37.869
🧪
O 3D parou de "ir e voltar": a caixa fica no meio da tela girando em torno do próprio eixo, e a câmera só orbita.
📄
E dá pra escolher o papel: kraft ou branco.
Pedido do dono em
16/09/2026, olhando a caixa girar:
"esse giro está muito superficial — a caixa vai lá longe,
passa muito perto da câmera, vai longe, depois volta. Deixa ela girando 360, parada, só virando ali; a câmera só sobe e desce,
vai pra um lado e pro outro, mas não pode mudar o objeto: ele fica fixo no meio da tela" — e
"todas as caixas vêm brancas; quero escolher papel branco ou papel kraft".
🔍
O que era: a câmera dava a volta em torno da origem da
chapa aberta, e o centro da caixa
montada não é esse ponto
(a base quase nunca está no meio da chapa). Por isso a caixa descrevia um círculo na tela.
✅
Agora: a caixa é recentrada a cada quadro (o pé no chão, o centro no eixo) e
ela gira;
arrastar move só a
câmera (sobe, desce, dá a volta), a roda aproxima, e nada disso tira a caixa do centro.
Arrastar não para mais o giro — quem para é o botão. Vale nas três telas que abrem o 3D (orçamento, Desenvolvimento e cadastro da caixa).
📄
Papel: seletor
kraft / branco no rodapé da janela, lembrado neste navegador. No kraft a arte sai
tingida pelo papel
(as áreas brancas da arte viram kraft, como na impressão de verdade — não existe tinta branca); no branco, a arte como está.
🔒 Clique fora da janela não fecha mais (a regra da v2.37.825, que esta janela tinha ficado de fora).
🔧 Por dentro: js/70-caixa3d.js — grupos giro (a caixa) e ajuste (recentragem por Box3 com o giro zerado),
trocarPapel, altura como alvo da câmera. Teste tests/caixa3d-camera-e-papel.test.mjs. Sem servidor, sem Luan.
v2.37.868
🎨
A ARTE ENTRA POR BAIXO DA FACA no orçamento — e o mesmo arquivo vai pro 3D, pro cliente, pra clicheria e pra facaria.
Pedido do dono em
16/09/2026, mostrando o módulo da MTX:
"a gente coloca a faca ou uma maleta, comprimento, largura e altura, ela monta o desenho; quando a gente adiciona o PDF,
aparece o desenho do PDF dentro da faca. Quero isso aqui, porque é isso que vai virar o 3D que o cliente visualiza.
É um arquivo só: o mesmo que vai pra clicheria e que o cliente aprova. Se eu trocar o arquivo, vira versão 2,
muda o 3D, e é a v2 que vai pro cliente."
🖼
Na tela do item: ao jogar o
.ai ou
.pdf no campo "🎨 Custo de tinta pela arte" (o mesmo de sempre),
a arte aparece
por baixo do desenho da faca, na
medida real lida do arquivo (camada "faca" → TrimBox → página),
com olho pra esconder e barra de opacidade. Corte e vinco com DXF: a arte cai
pose a pose no plano (girada nas fileiras invertidas do encaixe).
Maleta: centrada na chapa inteira. Arte maior que a chapa transborda de propósito — é sinal de que é a arte de OUTRA caixa.
🧪
"Ver a caixa em 3D", direto do item: corte e vinco monta pela faca do projeto (DXF ou desenho real);
maleta monta pela própria fórmula do orçamento (a planificação vira faca e o motor acha os 13 painéis sozinho) —
e a arte vai por fora, calibrada sozinha (com a MITTO a conta reproduz a calibração feita à mão na prova de 19/08).
📎
O arquivo é UM SÓ: ele sobe pro servidor e vira
versão no item (v1, v2…); trocar o arquivo num item
que já tinha arte é a v2 (a anterior fica guardada); reabrir o item traz a arte de volta por baixo da faca; o DXF do corte e vinco
também sobe como arquivo (uma vez só por conteúdo). Ao
virar pedido, a caixa cadastrada nasce (ou recebe) a mesma URL e versão.
Quando a linha tem elo com o
Desenvolvimento, a arte entra lá como a arte que o
cliente aprova no link (a v2 fecha as alterações
pendentes, como já era) e o DXF como a faca que vai pra
facaria; "puxar do orçamento" leva os dois junto.
E a ficha da
clicheria passa a sair com a última arte quando não há um PDF de clichê anexado à parte.
⚠️
O que NÃO está nesta versão: o 3D dentro do
link do cliente (o portal hoje não carrega o 3D e não pode receber o DXF cru) —
é a próxima frente. O elo com o Desenvolvimento só existe quando a linha já foi "puxada" pra lá.
🔧 Por dentro: js/101-arte-na-faca.js (porte do js/87 da MTX + arte por baixo + upload versionado + 3D do orçamento + maleta→faca),
ganchos no js/08 (orcDesenhar ×3, item, orcEditarItem, conversão, cadastro da caixa), js/23/js/23c (o quadro da chapa em svg.dataset.cvQuadro),
js/34 e api/src/routes/desenvolvimento.js (ficha do clichê). Teste tests/arte-na-faca-orcamento.test.mjs (37 checagens, 13 mutações acusadas).
Sem migration; Luan: pm2 restart só pra ficha da clicheria cair na arte.
v2.37.867
🚨 UM OVERHANG DIGITADO ERRADO CONGELAVA A TELA. O dono digitou 10.000 no
overhang sem querer e o orçamento travou. O motor do palete desce o overhang de 5 em 5 até a
regra do caminhão (1.200 mm) aceitar: com 10.000 são ~2.000 voltas de laço, medidos em
1,58 s POR TECLA — e a conta roda a cada dígito. Agora o overhang tem teto, e acima dele a
regra nunca aceitaria mesmo: medido em 302 casos onde o teto morde, 0 resultado diferente.
1.582 ms → 3 ms, com os mesmos números.
🛠 E a tela mentia sobre o overhang. Ela escrevia “overhang 10.000 mm” — o que foi
pedido — enquanto o motor tinha usado 235 mm. Agora sai o usado, e quando ele é menor
que o pedido a tela diz que foi a regra do caminhão que cortou.
📏 Dá pra ver o palete, como o dono pediu: a base que fica em cima
(“1.479 × 995 mm”), quanto passa de cada lado (“passa 140 mm de cada lado na largura · sobra
2 mm no comprimento”), a conferência do caminhão (“menor lado 995 mm ≤ 1.200 mm”) e a
ocupação do palete em barra e em % — 80%, 100%, 123%. Acima de 100% a carga passa da
borda, e a tela diz em quantos milímetros.
⚠️ O campo Lastro discordava do resultado, calado. O dono digitou 4 e a tela
respondeu 3. O campo é reserva (vale enquanto não há medida); quem manda é a medida da
caixa, exatamente como no módulo 8 do cadastro. O que faltava era dizer isso — e agora a linha
explica e ensina a apagar o campo.
📦 A paletização desce pro cadastro quando o orçamento vira pedido. A caixa nasce com o
palete inteiro já calculado, no mesmo formato que a tela de Caixas grava (é o
palParaSalvar do js/19, o mesmo do módulo 8): medido, nenhuma chave faltando e nenhum
valor diferente. Não precisa configurar palete de novo.
✅ E a regra da maleta e a da caixa aberta são as MESMAS do cadastro — porque é o
mesmo motor, não uma segunda conta. Medido lado a lado: maleta 280×215×190 → pacote
513×415, lastro 6, 7 camadas, 1.050 cx/palete nos dois; corte e vinco aberta (chapa 520×330,
peça inteira, 1 espessura, sem a regra da maleta) → lastro 8, 14 camadas, 2.800 cx/palete
nos dois.
🔧 Por dentro: teto do overhang em calcularLastro (js/19) —
(1200 + 2×maiorPeça − menorLadoDoPalete)/2, mais um limite duro de voltas;
jpOrcPaletizacaoPadrao (js/72) devolve baseL/baseC, passaL/passaC,
overhangUsado e ocupacao, todos derivados do mesmo palCalcular que
desenha a base (§9.13 — uma conta só); _orcPalBaseTxt e orcPaletizacaoDoItem
(js/08). Sem servidor, sem Luan. (Era pra ser a 866; a main ganhou a 866 do 3D no caminho.)
v2.37.865
🚨 A MESMA TELA mostrava DUAS contas do palete. O dono ajustou, dentro do bloco,
amarrado 50 e altura 2.400, leu ali mesmo "2 × 30 × 50 = 3.000 caixas/palete"
— e o campo, o cabeçalho e o nº de paletes continuaram em 1.400 / 29 paletes.
🔍 Quem PREENCHE o campo estava lendo o padrão global e ignorando o ajuste do
item; só o texto de dentro do bloco usava o que ele digitou. Agora os dois leem a
mesma conta: mexeu no bloco, muda em cima na hora — e apagar o ajuste volta ao
padrão sozinho.
🧱 O LASTRO agora aparece (era o que ele pediu pra conferir): "Lastro 2 pacotes na
base · amarração · calculado pela medida", com o tamanho do pacote e o
palete usado.
📏 Ganhou também Overhang máx. e o ⚠️ Palete FORA do padrão,
os mesmos do cadastro da caixa — e o aviso em laranja quando o palete não é o PBR.
⚠️ Os quatro ajustes valem só para aquela caixa; o que fica gravado no
orçamento é o resultado (paletes e caixas por palete), que é o número que
entra no custo do pallet.
v2.37.864
📦 O orçamento ganhou o módulo da PALETIZAÇÃO, dentro do item.
Pedido do dono em 16/09/2026, depois de procurar quatro vezes onde isso ficava:
"quando eu colocar as medidas no orçamento já aparece quantas caixas vai no palete…
esse mesmo módulo, mas quero clicar pra abrir se precisar mexer ou verificar se está
certo; como já temos um padrão configurado, no momento eu só preciso saber quantos
paletes eu vou usar naquele pedido".
✅ FECHADO ele já responde — "1 palete · 1.050 cx por palete" —
que é o que se precisa pra orçar. ABERTO mostra a conta inteira, com as MESMAS palavras
da seção 8 do cadastro da caixa (pacote → altura útil → camadas →
sugestão), e deixa ajustar amarrado, altura, palete e lastro só daquela caixa.
💰 E isso entra no CUSTO. O número de paletes é o mesmo que o
🧩 Insumos do Orçamento usa pra cobrar o pallet — sem ele, o custo completo
dizia "Paletes: não deu pra saber por pallet — não entrou no preço".
✂ Corte e vinco: ali C × L × A é só visual e quem manda é a
medida da chapa, que vem do 🎨 Projetar Corte e Vinco (ou do DXF). Sem o projeto aplicado
o módulo diz isso, em vez de ficar calado — era esse silêncio que fazia parecer
que a paletização não existia no orçamento.
⚠️ Os dois campos de sempre (Paletes e Caixas por palete) continuam ali dentro,
com os mesmos nomes por baixo: tudo que já lia ou gravava neles segue igual, e o que vai pro
documento continua sendo o resultado.
v2.37.863
🚚 "CARREGADO PARCIALMENTE · 3 de 5 paletes" num pedido que já tinha ido embora INTEIRO.
Você apontou a
POWERDENT TIPO 04 na Carteira:
"ainda está com esse problema no pedido
da power dent, não tem mais nada no estoque". E não tinha mesmo — o pedido estava
lá com o selo
🚚 CARREGADO PARCIALMENTE · 3 de 5 paletes · 5.782 cx e
zero linha no Estoque PA.
🔍 O que aconteceu. Esse lote tem
3 paletes (2.521 + 2.161 + 1.100 =
5.782 cx),
e os
3 saíram na mesma carga bipada, no caminhão do Reginaldo. O
5 era conta
errada: a
Coladeira lançou o MESMO lote duas vezes — em
21/08 com os paletes
1-2-3 e em
24/08 com os paletes
1-2 de novo — e o sistema, pra saber o tamanho do
lote,
somava os dois lançamentos: 3 + 2 = 5. Os paletes 4 e 5
nunca existiram.
🔑 E por isso o selo não fechava nunca. Quem
saiu sempre foi contado por
identidade (o mesmo número do QR da etiqueta: pedido + lote + posição), então
o máximo que ele chega é
3. Se o outro lado diz
5, a conta
3 de 5 fica
congelada pra sempre — e o pedido nunca vira
Carregado sozinho.
✅ O conserto: o tamanho do lote passou a ser contado pela
mesma identidade. Palete
carimbado duas vezes é
um palete. A POWERDENT TIPO 04 fica em
3 de 3 — ou seja,
sem selo nenhum, porque saiu tudo. Conferido contra a produção de hoje:
mais um
pedido estava no mesmo caso, a
TANGARA 07 FLOPS ÁGUA SANITÁRIA, que dizia
5 de
10 e agora fecha em
5 de 5.
👁️ Onde muda: no selo da
Carteira, no chip do card (
"saiu tudo (3 paletes)"
no lugar de "3 de 5 já saíram"), na
📜 Vida do pedido e em
todos os apps
— motorista, operador, encarregado, escala, vendedor, qualidade —, que leem o mesmo resumo
publicado pelo PCP.
🛡️ O que NÃO muda. Os selos de quem está
mesmo pela metade
continuam iguais:
JESSE CX 05 ASSADO 12 de 14,
EMPORIO PRIME FUNDO-B 3 de 4 e
GAIOTO CX 01
1 de 3 — os três com palete de verdade no PA, do jeito que a sua tela do estoque mostra. Dos
8 selos que a fábrica tinha, saíram
só os 2 falsos.
🔧 Por dentro: js/30-saidas-palete.js — spPaletesUnicos() (nova) colapsa o
palete repetido por paleteId (pedido+lote+seq, a mesma fórmula do QR e do livro de
saídas), com o carimbo mais novo vencendo o empate; spTotalDoLote() passou a
contar por ela nos dois caminhos (linha do PA e registros). O Estoque PA (js/03) ficou de fora de
propósito: lá a conta é em caixas e as duas inflações se
anulam (o produzido soma os dois lançamentos, 10.464 cx, e o desconto tira o palete repetido duas
vezes, 10.464 cx) — deduplicar só um lado deixaria 4.682 cx de estoque fantasma na
POWERDENT. 11 checagens novas e 4 mutações em
tests/carregado-parcialmente.test.mjs. Sem servidor, sem Luan.
v2.37.862
📦 Configurou a paletização, digitou as medidas e o palete NÃO aparecia.
Caso do dono em 15/09/2026, com tudo cadastrado certo.
🚨 A conta estava certa o tempo todo — 6 (lastro) × 7 (camadas) × 25
(amarrado) = 1.050 caixas por palete na caixa 280 × 215 × 190. Quem não
rodava era o gatilho: ele só chamava a conta se o padrão já tivesse
preenchido antes. Na ordem real de quem usa a tela — escreve o nome da caixa nova,
depois digita C × L × A — a primeira tentativa acontece sem medida
nenhuma, falha, e a partir daí o padrão nunca mais era chamado.
✅ Agora quem manda é a marca de CAIXA NOVA: digitou a medida, o palete aparece
na hora — nos três lugares (os campos Paletes e Caixas por palete, a linha
da conta embaixo deles e a linha 📦 Paletes do Custo completo).
⚠️ Caixa cadastrada continua intocada, e o número que você digitar na
mão também: quem protege isso é a guarda de dentro da conta, que nunca dependeu
dessa linha. Custo medido de refazer a conta a cada tecla: 0,066 ms.
v2.37.861
⚙️ A tela de Config. Orçamento virou uma LISTA DE NOMES que abrem no clique.
Pedido do dono em 15/09/2026: "essa tela está bagunçada, deixa ela mais
organizada, um embaixo do outro com os nomes, e quando clica abre — pra não ter que
ficar rolando a tela lá pra baixo".
🚨 Eram duas colunas: uma caixinha com as faixas e, do lado, UMA coluna só com SETE
seções empilhadas (setup, velocidade, limites, comercial, fiscal, paletização,
preço). Quem procurava a paletização tinha que rolar até quase o fim —
foi assim que ela ficou invisível, e o dono passou dois dias procurando onde configurar.
✅ Agora são 9 nomes, um embaixo do outro, cada um com o resumo do que está
valendo do lado direito — dá pra conferir tudo sem abrir nada. A
📦 Paletização padrão avisa em amarelo "não configurado —
a caixa nova fica sem palete". O que você deixar aberto continua aberto na próxima vez.
📝 E o orçamento passou a contar que a configuração existe. Quando falta
o padrão, a linha embaixo de "Caixas por palete" diz onde preencher — antes ela só
mandava digitar na mão, e não havia pista nenhuma de que existia um padrão.
🔧 Dois defeitos de tela no caminho: no Custo de setup, o nome da máquina
saía escrito por cima do "calculado R$ …/h" (os dois lados eram
nowrap e nenhum encolhia); e o botão "Salvar compensações"
virou "Salvar configurações" — ele sempre salvou a tela inteira, o nome
é que tinha ficado pra trás. Nenhum campo mudou de nome nem de lugar por dentro:
o salvar continua lendo tudo, inclusive as seções fechadas.
v2.37.860
🏁 Finalizar o pedido com saldo a terminar — registrando que faltou caixa, sem excluir nada.
Você pediu, com o
GRS TOYS E DOLLS 24126 na tela:
"eu tenho esse saldo aqui para terminar,
mas quero finalizar e deixar registrado que foi finalizado faltando caixa. Mas o botão que tenho aqui
é somente para excluir — e se eu excluir eu perco os apontamentos."
Você estava certo:
não existia essa porta. O pedido que produziu menos do que o cliente
comprou fica de propósito na fábrica (é o aviso
⏸ FALTA PRODUZIR na linha),
e as três saídas que havia eram
🔄 Reprogramar e
↩️ Reabrir
etapa — que mandam
produzir o resto — ou o
🗑️ Excluir, que leva o
pedido inteiro pra Lixeira.
Onde está: na
Carteira, na própria linha do pedido, ao lado do 📝 e do
🔢: o botão
🏁. (Também dentro do pedido, no ✎, como
🏁 Finalizar com saldo · faltam N.) Ele abre uma janela que mostra
quanto foi
comprado, quanto foi feito e quanto falta em cada caixa daquele número de pedido — no 24126
são as duas, a
CX M (faltam 4.192) e a
CX P (faltam 633) — e pergunta
o
motivo. Marcadas as caixas, um clique fecha todas de uma vez; desmarcando, fecha só a que você
quiser.
📝 O que fica registrado. No pedido fica escrito
FINALIZADO COM SALDO com o comprado, o
produzido,
quantas caixas faltaram, o motivo,
quem fechou e
quando — na
📜 Vida do pedido e num selo
🏁 verde na linha da Carteira ("faltaram 4.192 cx").
O aviso amarelo de
FALTA PRODUZIR daquele pedido se cala, porque agora ele tem resposta.
🔐 Nada é apagado (Regra Zero). Os
apontamentos continuam todos lá, os
paletes e as etiquetas também, e a
quantidade que o cliente comprou não é
reescrita — 22.000 continua 22.000, e quem conta o que faltou é o registro. O pedido só
sai da fila de produção: vira
Pronto e, se tudo o que foi produzido já
embarcou, o sistema o passa pra
Carregado sozinho, como sempre fez.
↩️ Fechou por engano? Abra o pedido (✎) e use
↩️ Desfazer o
encerramento: ele volta pro status em que estava e o saldo reaparece na fila. O registro de que tinha
sido finalizado
continua na Vida do pedido — história não se apaga.
⚠️ O que ele não esconde. Se ainda houver
material parado na fábrica
(chapa lançada que não passou na máquina, ou caixa cortada esperando a coladeira), esse
aviso
continua aparecendo na linha: fechar o pedido no papel não tira material do chão.
🔧 Por dentro: js/100-finalizar-com-saldo.js (fsFalta, fsFechado,
fsPodeFechar, fsSelo, fsAplicar, fsDesfazer); a marca
finalizadoComSaldo viaja no dados do pedido. A marca é conferida a cada
desenho — reabriu o pedido por qualquer caminho, ou produziu o saldo depois, e ela se cala sozinha
(nenhuma das quatro portas de reabrir precisa saber deste arquivo). 59 checagens e 3 mutações em
tests/finalizar-com-saldo.test.mjs. Sem servidor, sem Luan.
v2.37.859
🚚 O app do motorista dizia "Entregar 1" e abria em "Nada pra entregar agora".
Sua foto do app do REGINALDO: a aba 🚚 Entregar com o número 1 do lado e, embaixo,
"Nada pra entregar agora". Não era o app do motorista escondendo entrega — era o
número que estava sobrando.
O que aconteceu de verdade: a carga da placa ATN-5I22 foi bipada em 11/09 à 1h46 com
1 palete (TRANSBERNAL, MORANGO, 1.250 cx) e finalizada às 1h48. Às 1h58 ela foi
esvaziada no 🔧 Corrigir carga, com o motivo escrito: "bipado errado colou em outro romaneio".
O palete foi embora e a carga ficou sem palete nenhum — mas continuou pendurada no contador do
Reginaldo. Ele carregou esse 1 por quatro dias.
Por que o número e a tela discordavam: eram duas contas da mesma coisa. O contador da aba
somava as cargas que ainda faltavam; a lista somava as mesmas e mais uma regra escondida —
carga sem pedido identificado ela simplesmente não desenhava, calada. Como o card saía vazio, a
tela ainda caía no "Nada pra entregar agora". Foi 1 caso em 66 cargas finalizadas: só nasce
depois de uma correção que tira tudo.
O que mudou: agora o número da aba e o que aparece na tela saem da mesma lista — o que sai
de um sai do outro junto, não tem como discordar de novo. E a carga esvaziada não sumiu do sistema:
ela continua no ✅ Entregues do motorista, agora dizendo "carga sem palete — a expedição tirou
tudo na correção" em vez do "0 pedidos · 0 cx" sem explicação.
Dois casos que antes sumiam calados e agora aparecem com card: a carga esvaziada que saiu e
ainda não voltou (pra ele não perder o botão 🏁 Cheguei na fábrica, que fecha a viagem e tira
o caminhão da estrada na tela do escritório) e a carga com palete sem pedido identificado, que
agora avisa "fale com a expedição antes de sair".
Conferido no servidor antes e depois, nos 16 motoristas: o Reginaldo era o único com o
número diferente do que a tela mostrava (1 × 0) — agora é 0 × 0, e nenhum outro motorista mudou.
🔧 Por dentro: cargasParaEntregar() + cargaSemPalete() (painel_motorista) — uma
lista só, lida pelo motAbasHTML (o número) e pelo renderMinhasCargas (a tela);
o if(!peds.length) return '' virou _motCardSemPedido(c), que lê o motivo em
c.correcoes. 105 checagens e 6 mutações em
tests/motorista-badge-bate-com-a-lista.test.mjs, mais o snapshot real do servidor rodado
contra o código corrigido. Sem servidor, sem Luan — é só frontend.
v2.37.858
🗑️ Botão pra EXCLUIR um palete — só ele, sem apagar os apontamentos.
Você pediu: "lançou 1 palete de 181 a mais, eu tenho que excluir pra poder ir pro estoque" — e já
disse por que não dava: "o botão Resetar palete apaga todos os apontamentos, aí tem que fazer de novo".
Era isso mesmo. O ✏️ Corrigir palete só trocava a quantidade de um palete, e o
🗑️ Resetar paletes anula a etapa final inteira — pra tirar 181 caixas o operador perdia o
lançamento do turno.
Onde está: abra o pedido → Histórico → ✏️ Corrigir palete. Agora cada palete tem o
✔️ SALVAR (que já existia) e, do lado, um 🗑️. Ele tira aquele palete: a quantidade do
lançamento cai as caixas dele, o Estoque PA acompanha e todo o resto fica de pé — nenhum
apontamento é anulado, nenhum operador lança nada de novo.
🔖 E a sua pergunta: o QR muda alguma coisa? Não — e essa era a parte perigosa. O código do QR
de cada palete é formado pela posição dele no lote. Se a gente simplesmente tirasse o palete 14 da
lista, o 15 viraria 14: a etiqueta que já está colada passaria a valer por outro palete, a
bipagem da Expedição cairia no errado e a baixa do estoque também. Por isso, antes de tirar, o sistema
carimba o número de cada palete — aí quem fica continua com o mesmo QR de sempre. No exemplo dos
15 paletes: tirando o 14, os que ficam são 1…13 e 15, exatamente como estavam. As etiquetas já
impressas continuam valendo. O que envelhece no papel é só o "de 15", que vira "de 14" — por
isso, no fim, ele pergunta se você quer reimprimir (e nunca imprime sozinho).
🛟 O que ele NÃO deixa fazer. Palete que já foi bipado numa carga ou que já saiu do Estoque
PA não sai por aqui — ele avisa onde saiu e manda ajustar na Expedição, porque tirar aqui seria reescrever
uma carga que já foi embora. E o último palete do lançamento também não: pra tirar tudo é o
🗑️ Resetar paletes mesmo. Se o servidor recusar (ou estiver fora do ar), o palete volta na hora
e aparece o aviso — nada de sumir da tela e voltar no dia seguinte.
📋 Nada é apagado (Regra Zero). O palete tirado fica guardado no próprio lançamento, com
quem tirou, quando e por quê — igual ao registro anulado, que fica arquivado e legível.
v2.37.857
📏 O cadastro da caixa mostrava medida que NÃO estava salva — e o tablet do operador mostrava a certa.
Foi o que você viu na GAIOTO PAES · CX 01: no cadastro 35 × 368 × 601 × 368 × 601 (riscador
184 × 233 × 184) e no app do operador 0 × 366 × 599 × 366 × 599 (riscador 183 × 227 × 183). O
operador não estava errado — ele mostra exatamente o que está gravado. Quem mostrava número a mais era a
tela do cadastro: quando o campo de compensação está vazio, ela preenche sozinha com o padrão da onda
só pra você ver — e isso não fica salvo enquanto ninguém apertar Salvar. Aí as duas telas dizem
números diferentes da mesma caixa e a máquina é regulada pela menor.
Agora a tela avisa. Ao abrir uma caixa que está salva sem compensação aparece uma tarja amarela em
4 · Compensações por aba: "esta caixa está salva SEM compensação — o que está nos campos é a
sugestão da onda e ainda não valeu", dizendo que o tablet do operador está usando a medida sem elas.
Nada muda sozinho, nada é salvo sozinho — o aviso só conta o que está acontecendo, e some quando você
confere os números e salva.
🔎 E tem a varredura que você pediu, pra não acontecer com mais nenhuma. No alto de
Cadastros → Caixas passou a sair uma faixa com todas as caixas nessa situação, com o botão
abrir em cada uma. Conferido no cadastro de hoje: das 212 caixas, 160 estão completas e
5 estão sem compensação nenhuma — ECOLUBRI CX 02, ECOLUBRI CX 04, FARMASI 03,
FARMASI 04 e GAIOTO PAES CX 01. Caixa de corte e vinco, folha do facão,
micro/cartão e caixa inativa ficam de fora da conta: nelas o zero é o certo, e aviso que
grita à toa ninguém lê.
🔎 Busca na Carteira — achar o pedido sem rolar a tela toda. Você foi imprimir o
24184 (TANGARA) pro faturamento e ele parecia não estar agrupado. Estava — as 4 caixas têm o
nº 24184 e o cartão do pedido existe; ele só cai lá no fim, porque a carteira é ordenada por urgência e a
entrega é 25/09. Agora tem um campo de busca no alto da lista: digite o número do pedido, o cliente ou
o código da caixa e ele aparece na hora, com ✕ limpar do lado. Enquanto tiver texto no campo, a busca
olha todos os pedidos (as abas Hoje/Semana/Atrasados ficam de lado) — senão justamente o pedido de
entrega longe continuaria escondido. A tela diz isso embaixo do campo.
🔧 Por dentro: jpCompensacaoFaltando /
jpCaixasSemCompensacao e cxCompNaoSalvoAviso (js/08-cadastros.js) — uma régua só,
a mesma da faixa e da tarja; pedidoCasaBusca (js/01-core.js) é a MESMA régua que o relatório já
usava, pra tela e papel nunca acharem coisas diferentes. Nenhum número foi mudado em caixa nenhuma e nada é
salvo automaticamente. Testes: caixa-sem-compensacao (44 checagens, 9 mutações) e
carteira-busca (41 checagens, 9 mutações), os dois conferidos contra a versão anterior — sem o
conserto eles falham.
v2.37.856
🎨 A tela do Orçamento passou a ler as cores do arquivo — a primeira das telas.
O alicerce subiu na v2.37.854 sem ligar em ninguém. Agora a primeira tela lê dali, escolhida por você:
Orçamentos — o cartão da lista e a janela de montar o orçamento. Eram 105 cores escritas à mão
nesses dois lugares; agora são zero.
86 delas saíram idênticas — o arquivo já tinha exatamente a mesma cor. 19 mudaram, e é a
padronização que você aprovou vendo o antes-e-depois: Pendente (laranja da casa → laranja mais claro),
Reprovado (vermelho forte → vermelho claro, que lê melhor no fundo escuro) e Convertido
(azul-céu → o azul da marca). Os cinco selos de situação agora saem da mesma família de cores, então
quando as outras telas forem convertidas o mesmo status vai ter a mesma cor em todo lugar.
Nenhuma outra tela mudou. O arquivo de cores entra antes do CSS antigo de propósito: onde os dois
falam da mesma coisa, quem manda continua sendo o antigo. Só quem foi convertido lê do novo.
🔧 Por dentro: renderOrcamentos (js/08-cadastros.js) e
#modal-orcamento (sistema.html) com var(--token); três tokens novos no
css/00-tokens.css (os companheiros -rgb do roxo e do teal, e o verde da gramatura) —
nenhum valor existente foi alterado. A trava: 19 checagens e 4 mutações em
tests/orcamento-cores-do-arquivo.test.mjs, que reprova cor digitada na mão, token com nome
errado (esse não dá erro: o selo simplesmente sai sem cor) e a fiação fora de ordem.
Sem servidor e sem migration — nada pro Luan.
v2.37.855
📐 A lista de pedidos passou a ocupar a tela toda — e o cartão parou de quebrar palavra por palavra.
Suas fotos mostraram o estrago: o cartão do pedido saía "📦 / Pedido / 23359 / FK / GRUPO / 19 / caixas /
26.336 / un", uma palavra por linha, com os botões escapando pra fora da direita — e metade da tela
vazia do lado. Suas palavras: "está muito apertada, vamos colocar uma debaixo da outra",
"deixa na tela toda com facilidade de visualização".
1 · Pedidos na largura inteira. O Dashboard era duas colunas (pedidos à esquerda, cronograma à
direita) desde sempre. Com a letra grande do seu Mac, sobravam uns 300 pixels pros pedidos — daí a
quebra. Agora é uma coluna só: os pedidos em cima ocupando tudo e o cronograma embaixo,
também inteiro. As duas coisas ganharam espaço; nenhuma sumiu.
2 · O cartão do pedido ficou agrupado, em três faixas. Nome e número numa linha
(📦 Pedido 24166 · FK GRUPO), os números embaixo (3 caixas · 64.000 un · R$ 198.278,40 ·
Entrega 2 datas · 🔮 previsão) e, na terceira, os selos e os botões. Nada mais espremido de lado,
nada mais saindo pra fora.
3 · 🧾 em todo cartão — inclusive na caixa solta. Como você pediu: o pedido sem número (que não
vira cartão de pedido agrupado) também tem o botão agora — nele sai a folha só daquela caixa.
4 · E na tabela do 🏭 PCP → Carteira, que é onde você trabalha. Aqui estava o motivo de você não
achar nada: eu tinha posto os botões no Dashboard e na janela do pedido, duas telas que você
não usa. Agora cada linha do PCP tem, do lado do + e do ✎: 🧾 (imprimir pro
faturamento), 📅 (trocar a data) e 🔢 (trocar o número) — valendo pro pedido inteiro,
todas as caixas dele de uma vez.
🔧 Por dentro: .main-grid numa coluna e o cabeçalho do grupo empilhado no
css/main.css (media query não resolveria: quem é estreito é a coluna, não a janela);
ação faturar no bindOrderActions e no bindRowActs (js/01), com a
chave sendo o número do pedido ou, sem número, a própria caixa. Sem servidor e sem migration —
nada pro Luan.
v2.37.854
🎨 As cores do sistema ganharam uma fonte de verdade — por enquanto só o alicerce, sem mexer em nenhuma tela.
Hoje cada cor está escrita à mão, espalhada: o mesmo verde de "entregue" aparece com três tons diferentes
dependendo da tela, e trocar um azul significa caçar o código em dezenas de arquivos. O conserto disso estava
pronto e parado desde 05/09, numa frente à parte.
Entrou só a base: css/00-tokens.css (todas as cores da casa, os trios de status, tema claro
e versão pra impressão), js/00-tokens.js (pro JS ler a cor do CSS em vez de guardar a sua) e
api/src/lib/cores.js (o espelho, pros e-mails que a API manda). Nenhuma tela foi ligada neles
ainda — então nada mudou de aparência, e não havia como quebrar nada hoje.
Por que não veio tudo de uma vez: a frente foi escrita 274 versões atrás. Trazer os 109 arquivos dela
agora seriam 153 pontos de conflito pra resolver na mão, em código de cor — onde errar não dá
erro, só sai com a cor trocada. E as 16 telas novas feitas desde então (Planejamento, FSC, Estoque geral,
Percurso, Corrigir carga, Pedido em lote…) ficariam de fora, com cerca de 300 cores ainda na mão. Num sistema em
que o selo é o status, selo com a cor errada é lido como status errado na fábrica.
Como segue: uma tela por vez, cada uma com a sua versão e o seu teste — a regra da casa para correção em
lote. Diga por qual quer começar.
🔧 Por dentro: os três arquivos entraram sem nenhum <link>
ou <script> apontando pra eles, de propósito; quem ligar a primeira tela leva a fiação junto.
Sem servidor e sem migration — nada pro Luan.
v2.37.853
⏸ A onduladeira também aponta PARADA — e é isso que faz a velocidade dela ser verdade.
Seu pedido: "coloca apontamento nas paradas tbm". Sem parada apontada, o tempo da rodada é tempo de relógio:
uma hora parada esperando papel viraria "a onduladeira é lenta", e o número que ela ganhou ontem nasceria errado.
No app dela, enquanto está rodando aparece o ⏸ Parei agora. Ele pergunta o motivo — os mesmos motivos das
outras máquinas (falta de papel, quebra de máquina, manutenção, abastecimento/troca de bobina, aguardando PCP, falta
de programação, refeição, troca de turno, outro). Durante a parada o card fica laranja com "⏸ PARADA — Falta de papel ·
desde 09:20 (40 min)" e um botão ▶ Voltei a rodar. O card também mostra "rodando desde 07:12 · 2h10 de
máquina · 40 min parada" e a lista das paradas da rodada.
A velocidade passou a ser do tempo de MÁQUINA, não do relógio: no Planejamento sai "X chapas/h (N rodadas,
Y chapas em Z h de máquina, fora W h de parada)". Assim a parada aparece como parada — que é um problema de
abastecimento ou manutenção — e não disfarçada de máquina devagar.
Por que os motivos são os mesmos das outras máquinas: motivo inventado aqui não seria reconhecido pelo OEE
nem pelos relatórios de parada, e a onduladeira ficaria com uma linguagem própria. A lista é um recorte — "limpar clichê"
e "ajuste de impressão" são da Slotter, não dela.
Detalhes que evitam número torto: parada esquecida aberta é fechada no lançamento (a rodada acabou, ela acabou
junto); Esc no motivo desiste em vez de apontar parada sem motivo; e as paradas são limpas junto com o relógio
quando a rodada é lançada.
🔧 Por dentro: `ondParar`/`ondVoltei`/`ondParadasMin` no painel_onduladeira.html, gravando `paradas[]`,
`paradaMin` e `rodandoMin` na linha do programacao.lancamentos[]; `velocidadeOnduladeira` (js/83) passou a
usar o rodandoMin. 100 checagens e 38 mutações. Nada pro Luan.
v2.37.852
⏱ A ONDULADEIRA PASSOU A APONTAR PRODUÇÃO — e agora ela tem chapas/hora medidas, não cadastradas.
Seu pedido: "coloca apontamento de produção na onduladeira". Veio do buraco que apareceu ontem medindo a fila de
chapa: a onduladeira era a única máquina do fluxo sem produção apontada. As outras três gravam operador, início,
fim e paradas; ela só dizia quantas chapas saíram — nunca em quanto tempo.
No app da onduladeira, em cima do "📦 Lançar produção", entrou o botão ▶ Comecei agora. Ele marca a hora;
o card passa a mostrar "⏱ rodando desde 07:12 · 1h20"; e quando você lança, a rodada fica gravada com o tempo.
Tem ↻ recomeçar se precisar remarcar.
No 📆 Planejamento, no quadro da chapa, a linha da onduladeira passa a mostrar o medido ao lado do cadastrado:
"⏱ Medido na máquina: X chapas/h (N rodadas apontadas) → Y chapas/dia · Z% do que o cadastro promete". Enquanto
ninguém apontar, ela diz "ainda sem medição" — nunca um número inventado.
Três decisões que valem saber:
• Esquecer o ▶ não trava nada. O lançamento continua igual ao de sempre; aquela rodada só fica sem tempo. Travar
a produção por causa de um campo novo seria pior que a falta do dado.
• Correção não conta como produção. Quando você corrige o total, aquele número troca o anterior — medir com ele
contaria a mesma chapa duas vezes.
• Rodada de menos de 10 minutos fica de fora da média: é digitação, não produção. É a mesma régua que o cadastro
de velocidade das caixas já usa.
🔧 Por dentro: o apontamento entra no programacao.lancamentos[] (campo aditivo, sem migration), e
não em pedido_registros — lá o registro é somado como caixa pronta, e a onduladeira faz
chapa: uma etapa que o etapaDoRegistro não conhecesse cairia em "outro" e a chapa entraria no lugar
da caixa, inflando o Estoque PA (o mesmo defeito que a v2.37.100 fechou).
ondBlocoRelogio/ondMarcarInicio no painel_onduladeira.html e
velocidadeOnduladeira no js/83. 99 checagens e 37 mutações em
tests/planejamento-semanal.test.mjs. Nada pro Luan.
v2.37.851
📦 A carga em andamento passou a viver no BANCO — celular que desliga não prende mais o caminhão. Caso de 09/09/2026: o expedidor estava bipando os paletes com o caminhão já carregando e o celular desligou sozinho. Não deu pra finalizar, a carga ficou em aberto, ele tentou entrar de outro celular e não achou nada — "ficou preso dentro do cache do celular desligado".
🔎 Por que acontecia. A carga do caminho escala/avulso nascia e vivia no armazenamento do próprio aparelho, e era só de lá que o app a lia ao abrir. A cópia que sobe a cada ~12 s desde a v2.37.359 servia pro escritório ver "carregando agora" e mais nada: ninguém lia de volta. No segundo celular o ▶ do caminhão criava uma carga nova e zerada — e a de verdade ficava pendurada no servidor sem dono. (No Modo Carregamento por plano isso nunca aconteceu: lá a bipagem sempre subiu na hora e o app junta o que veio do servidor. Faltava justamente no caminho mais usado da doca.)
📥 Agora cada toque grava no servidor na hora, palete a palete: salvar no aparelho passou a ser salvar nos dois lugares. Aparelho que morre perde, no máximo, a bipada que estava na mão — e a carga inteira sobe de novo no próximo palete que passar, então ficar sem internet no meio não perde nada.
▶ E qualquer aparelho retoma. Na tela inicial do app aparece 📦 CARGA ABERTA com a placa, o cliente, quantos paletes e quantas caixas já foram bipados e a hora da última bipada e quem bipou — um toque em Retomar e o carregamento continua de onde parou, em qualquer celular. O próprio ▶ da escala passou a continuar a carga aberta daquela viagem em vez de começar do zero, que era onde nascia a carga duplicada. Quem pode retomar: qualquer expedidor (decisão do dono — se o celular do titular morreu, o caminhão não pode esperar).
🤝 Dois celulares na mesma carga não se atrapalham mais: cada palete é gravado na sua própria chave, então o que um bipa aparece no outro sozinho (e o app avisa "2 paletes bipados em outro aparelho entraram nesta carga"). E o celular que ressuscita depois não republica uma carga que o colega já fechou — ele avisa que ela foi finalizada e libera a tela.
🛟 Nada se apaga (REGRA ZERO). Tirar um palete da carga vira uma marca de remoção que viaja pros outros aparelhos — sem ela, o palete removido voltaria na próxima junção. E o registro da carga aberta só sai do servidor depois que a carga fechada gravou de verdade (a lição da v2.37.114: apagar o backup antes da resposta do servidor foi o que já sumiu com bipagem).
🔧 Por dentro: js/80-carga-viva.js + o doc cargas_bips — keyed por carga e por palete, gravado por merge (§9.3: lista inteira por PUT foi o que engoliu 6 romaneios em 21/08). O doc cargas continua igual e é ele que manda no que está fechado: carga finalizada nunca volta a aparecer como aberta, e casca vazia não vira cartão (v2.37.482). 34 checagens e 6 mutações em tests/carga-viva-no-banco.test.mjs. Sem migration e sem Luan — o doc nasce sozinho no primeiro merge.
v2.37.850
🏭 A CHAPA QUE PRECISA FICAR PRONTA — e até que dia e hora.
Você pediu: "mede a fila de chapa contra a onduladeira" e, logo depois,
"quero o dia e hora da disponibilidade das chapas pra dar tempo de fazer a produção". Entrou no
📆 Planejamento, embaixo do dia a dia.
O prazo de cada chapa é a hora em que o corte dela começa — não a data de entrega do pedido. Para cada dia sai a
lista: até que horas cada chapa tem que estar na máquina, o cliente, a caixa e quantas chapas (não caixas: com
pose, uma chapa vira duas caixas, e pedir em caixa dobraria o papel).
🚨 O que sai em vermelho: "na véspera". Corte que começa às 05:00 não tem manhã para esperar a onduladeira — a
chapa tem que estar pronta no dia anterior. Hoje são 3 assim; é o prazo que ninguém enxerga olhando só a data.
Os números da sua fila agora: 55 pedidos · 339.620 chapas nas duas semanas. Hoje 79.020 chapas, amanhã
87.000 — o que dá 90% e 99% do dia cadastrado da onduladeira.
⚠️ E aqui a tela para de afirmar, de propósito. A onduladeira está cadastrada em 10.000 chapas/h × 8,8 h =
88.000 chapas/dia, mas ela é a única máquina do fluxo sem apontamento de produção: os lançamentos de chapa entram
em bloco (medido: de 950 a 332.621 num mesmo dia), então não há como o sistema dizer se ela dá conta. A tela mostra a
fila e o que o cadastro diz, lado a lado, dizendo qual é qual. Se aquele número não for o de hoje, ele se ajusta
em Fluxo / Cronograma.
🔧 Por dentro: `filaDaChapa` + `quadroChapa` no js/83-planejamento-semanal.js, sobre a mesma previsão do dia
a dia; as chapas saem do `posesDoPedido` (js/01), a régua que a Programação e a onduladeira usam desde a v2.37.780/782.
94 checagens e 34 mutações em tests/planejamento-semanal.test.mjs.
Sem servidor e sem migration — nada pro Luan.
v2.37.849
🕐 No 📆 Planejamento: o almoço e o turno de cada máquina na barra, a conta das horas corrigida, e a marca de "sem chapa" passou a olhar a CHAPA.
Você pediu, olhando a tela: "quero com horário de almoço também, e tem que corrigir o turno de cada máquina — porém
ele não anda como o cronograma, é somente um visual pra ver como vamos andar com a semana". É isso que ele é.
1 · A barra agora mostra o turno de cada máquina. A parte hachurada é hora em que aquela máquina
não está aberta — a Coladeira abre 07:00 e fecha 16:48, a Slotter vira a noite até 01:36. Antes o fundo vazio
parecia "máquina livre" onde ela nem existe. E a faixa amarela é o almoço, com o
horário quando você passa o mouse.
2 · 🚨 A conta das horas estava errada — e era ela que fazia a Coladeira parecer estourada. Ela aparecia com
9,8 h num turno de 8,8 h, todo dia. Número impossível: eu estava somando o relógio em vez do
trabalho. O pedido da JESSE ia das 08:41 às 14:13 — 5,5 h de relógio, mas 1 hora daquilo é almoço, então
são 4,5 h de produção. A diferença batia exatamente 1 h (na Máq. A, com 2 turnos, eram 2 h). Corrigido, a Coladeira
fica em 8,8 h de 8,8 h: cheia, não estourada. Era o tipo de número que faz contratar turno pra um problema que
não é aquele.
3 · A faixa amarela de "sem chapa" passou a olhar a chapa, não o status. Você apontou a NACON:
"mas NACON está como programado, e isso?" — barra cheia, com cara de quem tem material, num pedido de
27/08 parado há 18 dias e com ZERO chapa lançada. É que "programado" e "reprogramado" entram no cronograma
sem exigir material. Medido na sua carteira: 15 dos 17 pedidos que o cronograma planeja não têm chapa.
Agora a faixa amarela embaixo da barra é falta de chapa, seja qual for o status.
4 · Quando uma máquina não cabe, a tela diz o que fecharia o buraco — "faltam 18,3 h · 3,7 h a mais por dia
nos 5 dias que sobram · ou 3 sábados · ou o 2º turno nesta máquina" — e avisa quanto daquilo é pedido que já
venceu (na Coladeira, 42,7 h das 62,3 h são dívida atrasada, não demanda da semana).
Sobre a Coladeira: conferi se o gargalo era cadastro de velocidade desatualizado — não é. Ela roda mais
rápido que o cadastro em várias caixas, mas isso explica só 2,1 h das 56 h. A Coladeira está mesmo carregada, e
a maior parte disso é atrasado acumulado.
🔧 Por dentro: `minutosProdutivos`, `foraDoTurno`, `pausasDaMaq` e `saidas` no
js/83-planejamento-semanal.js; a marca agora vem do `temChapa` (js/01) e a fila da previsão passou a
obedecer a 🔥 prioridade do `jpPrioPeso`, a mesma que a v2.37.838 pôs no cronograma.
86 checagens e 31 mutações em tests/planejamento-semanal.test.mjs.
Sem servidor e sem migration — nada pro Luan.
v2.37.848
📅 Trocar a data do pedido inteiro (ou só de uma caixa) — e as ações do pedido agora estão no cartão, onde você procura.
1 · "Lancei e sumiu" / "não achei aonde faz isso". Você tinha razão nas duas. O pedido não sumia:
a lista estava num filtro ligado de antes (ATRASADOS, HOJE, EM PRODUÇÃO) ou numa aba que não é a
carteira — e pedido recém-lançado é "programado", com entrega lá na frente, então não entrava em nenhum desses
recortes. Agora, ao lançar, a tela volta pra carteira inteira (filtro TODOS) sozinha.
E o "não achei": a janela do pedido — a que tem 🧾 Imprimir pro faturamento — só abria pelo
cronograma. No cartão da carteira, clicar no pedido só abria e fechava a lista de caixas. Consertado de
três jeitos: o número do pedido virou clicável (abre a janela), os botões 📅 data e
🔢 número entraram no próprio cartão, ao lado do 🧾 faturamento que já estava lá, e o
botão de imprimir ganhou destaque dentro da janela.
2 · 📅 Trocar a data — de todas de uma vez, ou individual. Como você pediu. A janela mostra a
lista das caixas do pedido, todas marcadas: se o cliente empurrou o pedido inteiro, põe a data nova e
confirma; se foi só uma caixa, desmarca as outras. Tem "marcar todas" e "desmarcar" pra ir rápido.
Os cuidados: caixa que já saiu (carregada, carregado parcial ou entregue) aparece na lista
travada, com o motivo — a entrega dela já aconteceu, e reescrever a data depois do fato mentiria no
atraso e na pontualidade do cliente. Pedido reprogramado tem duas datas no sistema e elas
andam juntas. A data original (com que o pedido nasceu) nunca é mexida — é dela que sai o
"quantos dias empurrou". E cada troca fica escrita na vida do pedido.
🔧 Por dentro: pedDataAbrir / pedDataAplicar no js/01-core.js + a janela
modal-ped-data, que fica depois do popup no HTML de propósito (mesmo z-index: quem vem
depois é quem fica por cima — foi o defeito que apareceu no teste); o lançamento em lote passou a normalizar
filtro e aba (js/86-pedido-lote.js). +30 checagens e 18 mutações (todas acusadas) em
tests/pedido-lote-prioridade-faturamento.test.mjs. Sem servidor e sem migration — nada pro
Luan.
v2.37.847
🔎 "Está configurado certo?" — um comando responde, e 12 provas do faturamento voltaram a rodar
🧰 O conferidor do emissor. node scripts/focus-conferir.mjs responde as três perguntas da configuração de uma vez: o token está no lugar e é aceito? a JP está cadastrada lá? o certificado dela está instalado e até quando vale? 🔐 O token nunca é impresso — nem inteiro, nem pedaço, nem em mensagem de erro: saída de script acaba em print e em WhatsApp.
🚨 E o achado do dia: 12 provas do faturamento estavam CEGAS desde 08/09. Elas só rodam com o Docker ligado, e ele estava desligado — então nunca reprovavam. Com ele no ar, apareceram quatro expectativas velhas, todas de correções que já tinham sido feitas: uma cobrava de volta as 4 cópias da escolha de perfil fiscal que a v2.37.717 unificou, outra contava "2 rotas POST" quando a Fase 4 trouxe mais três, e outras duas não mandavam a natureza da operação que a v2.37.822 tornou obrigatória.
✅ O que isso vale: é a primeira vez que a pré-nota inteira — numeração por empresa, perfil da caixa, unidade, texto do item, Simples Nacional — roda contra um Postgres de verdade desde que a Onda 1 foi escrita. Passou nas 31. Até hoje essa metade estava anotada como "pulada", e pulado não é verde.
🧪 Uma prova que engolia o erro: duas pré-notas do teste não eram conferidas, então falha virava "TypeError: undefined" em vez da mensagem. Agora o motivo aparece escrito.
⚖️ O banco de teste ficou coerente: a empresa nasce "cumulativo" (é o que a JP tem cadastrado) e os perfis semeados foram alinhados a ela. Isso é escolha de teste, não resposta fiscal — quem prova o conflito de regime continua sendo o teste próprio dele, e a resposta de verdade é do contador.
🔧 Por dentro: scripts/focus-conferir.mjs (novo), FOCUS_NFE_TOKEN documentado no .env.example, e o preparador do banco de teste ficou coerente.
v2.37.846
🧾 EMITIR: a nota sai daqui, vai ao emissor e volta com chave, protocolo e DANFE — o caminho completo da Fase 4. Três botões novos na API: Emitir, Consultar e Cancelar (este último fala com a SEFAZ de verdade, não é o "cancelar teste" da pré-nota).
🚨 A trava que mais importa: nota autorizada NÃO sai de novo. Reenviar não é "tentar de novo", é uma segunda nota do mesmo faturamento — e a segunda não se desfaz apagando: desfaz-se com cancelamento na SEFAZ, prazo de 24 horas e conversa com o contador. Só rascunho e rejeitada podem ser mandadas.
🛟 E a nota é marcada ANTES de sair. Se a internet cair no meio do envio, ela fica como EM PROCESSAMENTO, nunca volta para rascunho — porque ela pode ter chegado lá. Quem responde isso é o botão Consultar, não um palpite nosso. Voltar para rascunho nessa hora é exatamente como nasce a nota duplicada.
🔒 Produção ainda não sai por aqui, de propósito. A sequência de numeração oficial desta casa só existe para o ambiente de teste — virar a chave é decisão do dono e trabalho de numeração, nessa ordem. Ambiente de produção recusa e explica.
🙅 Falta de dado recusa antes de enviar, com a lista na tela; e status que eu não conheço não vira estado: se o emissor responder algo novo, eu guardo a resposta crua e digo que não sei, em vez de escrever "autorizada".
🔑 Emitir pede permissão maior. A pré-nota é ensaio e pede só Baixa; fazer sair documento fiscal pede 🧾 Cadastro fiscal — Admin ou Financeiro. Quem mexe no fiscal é quem responde por ele.
🔧 Por dentro: migration 049 (de qual emissor saiu cada nota e com que referência — trocar de emissor no cadastro não reescreve a história das antigas), api/src/lib/nfe-emissao.js e três rotas em api/src/routes/nfe.js. 48 checagens e 7 mutações em tests/nfe-emissao-travas.test.mjs.
⚠️ Precisa do Luan: npm run db:migrate (migration 049), a variável FOCUS_NFE_TOKEN no .env da API, e pm2 restart all. E precisa do dono: cadastrar a JP no painel do emissor e subir o certificado A1 lá.
v2.37.845
🚀 A ponte com o emissor — o primeiro pedaço de código que pode fazer sair uma NOTA DE VERDADE — começo da Fase 4. O dono decidiu em 13/09: a nota sai por provedor de API (quem assina o XML, fala com as 27 SEFAZ, cuida da contingência e devolve o DANFE é ele), com certificado A1.
🧱 O que entrou: o tradutor entre a nota que o nosso motor já calcula e o formato que o provedor espera — cabeçalho, emitente, destinatário e os itens com ICMS, IPI, PIS e COFINS. Os nomes dos campos foram conferidos na documentação do provedor hoje, um por um; nada foi escrito de memória.
🙅 Falta de dado NÃO vira chute. Aquela lista de pré-voo que a v2.37.826 passou a mostrar como aviso na pré-nota agora recusa: NCM com 7 dígitos, CNPJ com dígito errado, cliente sem CEP ou sem código IBGE, IPI suspenso sem código de enquadramento — nada disso sai daqui pra virar nota assinada.
⚖️ Campo de imposto só quando há imposto. Base zero num CST que não tributa (a industrialização, com ICMS e IPI suspensos) é rejeição na SEFAZ. Quem decide a entrada do grupo é o valor calculado, não a alíquota do cadastro — um rascunho deste arquivo deixou passar exatamente isso, e o teste pegou. PIS e COFINS continuam na industrialização: zerar "porque é suspensão" seria errado (medido nas notas reais).
🔐 O token não passa pelo banco. No cadastro fica só o nome da variável de ambiente; o valor vive no .env do servidor — a mesma regra do certificado, que a v2.37.716 fechou. Sem a variável, a rota recusa e diz o que pedir ao Luan.
🛟 E o ambiente errado não acontece por descuido: ambiente indefinido cai em homologação, nunca em produção. Cancelamento e carta de correção já entram com a exigência de justificativa de 15 letras da SEFAZ, barrada aqui antes de gastar chamada.
🔧 Por dentro: api/src/lib/focus-nfe.js (novo). 62 checagens e 7 mutações em tests/focus-nfe-payload.test.mjs. Ainda NÃO emite: falta a rota que grava chave, protocolo, XML e DANFE — é o próximo passo.
v2.37.844
🧭 Quem é o cliente da nota passou a sair do CADASTRO — a tela só confere — quarto item da Onda 1 (achado F-7). A pré-nota recebia o destinatário inteiro do navegador: nome, CNPJ, IE, município e a UF de destino.
💰 Por que isso é dinheiro: é a UF que escolhe a linha da tabela de alíquotas — ou seja, a alíquota de ICMS da nota. Com ela vindo da tela, uma aba aberta desde ontem muda o imposto de uma nota que vai ser assinada. É a mesma porta que a v2.37.716 fechou no cadastro fiscal, aberta um andar acima.
🔗 E a nota não tinha dono: o servidor até sabia conferir o cliente, mas só aceitava id no formato do banco — e a tela manda o código do cadastro, que é outro formato. Resultado: a coluna do cliente na nota ficava SEMPRE vazia. Agora ela é preenchida, e nota sem dono deixa de existir.
🙅 Divergiu, recusa — e mostra os dois lados. Tela dizendo MG e cadastro dizendo SP não vira escolha silenciosa: a pré-nota para e mostra os dois, pra você decidir quem está errado. O mesmo vale pra "não contribuinte" na tela quando o cadastro tem Inscrição Estadual, que muda o DIFAL da nota inteira.
🧾 Campo de IE vazio não é "isento". Isento é uma condição declarada (a palavra ISENTO escrita no cadastro); vazio é cadastro pela metade. Nesse caso a escolha da tela continua valendo — com aviso.
✈️ Novo: o PRÉ-VOO do cadastro. Toda pré-nota agora lista o que a nota real não vai passar sem — CNPJ com dígito errado, IE em branco, endereço, CEP, código IBGE do município. É pra isso que a pré-nota serve: descobrir barato. Na emissão de verdade, a mesma lista vira recusa.
🔧 Por dentro: api/src/lib/destinatario.js (novo — DV de CNPJ/CPF, indIEDest, pré-voo e a leitura do cadastro por id do banco ou código da tela). 48 checagens e 7 mutações em tests/destinatario-vem-do-cadastro.test.mjs, com a pré-nota rodando contra um banco de mentira. Precisa do Luan: pm2 restart all (sem migration).
v2.37.843
⚖️ O PIS e a COFINS passam a obedecer o regime da EMPRESA — e o sistema para de escolher sozinho — terceiro item da Onda 1 (achado F-3, um dos três críticos). O campo "regime de PIS/COFINS" existe no banco desde agosto e nenhum cálculo lia: quem mandava era o cadastro do produto.
🚨 O que foi encontrado: a empresa está cadastrada como Lucro Presumido, que por lei paga 0,65% + 3%. Os cadastros de produto, copiados do Sectra, estão com 1,65% + 7,6%, que é de Lucro Real — em 6.008 itens do 1º semestre. Uma das duas coisas está errada, e as duas são graves: ou a empresa é Lucro Real e muda toda a apuração, ou o Sectra vem emitindo divergente.
🙅 O sistema NÃO escolhe. Ele passa a recusar a pré-nota quando os dois se contradizem, com uma mensagem que mostra os dois números lado a lado e manda confirmar com o contador. Isso é de propósito: é esse "não" que força a conversa, em vez de sair uma nota "quase certa".
🆕 Na tela 🏢 Empresas: campo novo Regime de PIS/COFINS, que nasce em "não respondido" e diz na etiqueta que a resposta vem do contador. Deixar em branco não apaga uma resposta já dada.
📉 O produto ainda pode pagar MENOS — isenção, alíquota zero, monofásico — mas só nos CST em que a lei permite e escrevendo a base legal no cadastro. Sem o motivo escrito, recusa: nota que ninguém consegue defender depois não deve sair.
🔧 Por dentro: migration 048 (tabela fiscal_pis_cofins_regime com vigência — em 2027 a CBS substitui as duas) e api/src/lib/fiscal-pis-cofins.js. A migration não altera o regime de ninguém. Não vale para o Simples, onde PIS/COFINS estão dentro do DAS. 52 checagens e 6 mutações em tests/regime-pis-cofins.test.mjs.
⚠️ Precisa do Luan: npm run db:migrate (migration 048) + pm2 restart all. E precisa do contador: é a pergunta nº 1 do documento de 08/09.
v2.37.842
📐 A CHAPA saía na nota com o NCM e o IPI de CAIXA — segundo item da Onda 1 (achado F-2). O cadastro fiscal da chapa já existia desde agosto (NCM 4805.25.00, IPI 3,25%, unidade M2) e o sistema nunca o escolhia: a busca do cadastro padrão estava chumbada em "PADRÃO — CAIXA".
💰 O tamanho: a nota de uma chapa levava IPI de 15% em vez de 3,25%, com o NCM e a unidade errados junto. Pelos números da própria atualização 042: R$ 2,08 milhões de IPI cobrado onde o certo seria R$ 450 mil por semestre. E classificação fiscal errada é multa de 1% do valor da operação, fora o imposto a mais.
✅ Agora quem decide é o cadastro do produto, lido no servidor — a mesma régua que as telas já usam pra saber se algo é chapa ou caixa (inclusive a exceção da caixinha de micro-ondulado, que é caixa mesmo tendo onda micro). Chapa sem cadastro fiscal de chapa não cai no de caixa: a pré-nota recusa e explica.
🔒 E o servidor não aceita palpite: a decisão sai do banco, nunca de um campo que a tela mande — seria a porta que a v2.37.716 acabou de fechar.
🔧 Por dentro: api/src/lib/caixa-natureza.js (novo), o prefixo do perfil padrão virou parâmetro em fiscal-perfil.js, e a pré-nota e o GET /produto/:caixaId escolhem pela família. 40 checagens e 5 mutações em tests/perfil-chapa-x-caixa.test.mjs — entre elas, as duas cópias da régua (a do servidor e a do js/08) rodando lado a lado em 1.456 combinações, que falha se elas discordarem em qualquer uma. Precisa do Luan: pm2 restart all.
v2.37.841
📋 Toda pré-nota nascia como VENDA — agora a tela pergunta de quem é o papel — primeiro item da Onda 1 da auditoria fiscal (achado F-1, o mais grave da lista). A tela nunca mandava a natureza da operação, e o servidor assumia venda em tudo. O motor da industrialização existe desde agosto e ninguém nunca chegava nele pela tela.
💰 O tamanho: medido no Sectra, jan–jun/2026 — 2.044 itens saíram como venda (5101) e 763 como industrialização (5125), estes com ICMS e IPI zerados. Somando o ciclo, ~41% dos itens. Emitir esses como venda destaca imposto que a nota real não tem — e imposto destacado é devido, com o cliente creditando o que não podia.
🆕 Na tela: campo Natureza da operação no topo da pré-nota, com três respostas — o papel é da JP · o cliente mandou o próprio papel · o papel veio direto do fornecedor do cliente. Ele nasce vazio e o botão "Calcular e gravar" fica travado até você responder: "ninguém respondeu" não pode virar "é venda". Se o cliente tiver papel guardado aqui em nome dele, a tela avisa quantos quilos — mas não escolhe por você, porque o sistema ainda não liga o pedido à bobina que ele gastou.
🔢 São DUAS industrializações, não uma: 5124 quando o cliente manda o próprio papel, 5125 quando o papel vem direto do fornecedor dele. O Sectra usa 5125 em tudo — está na lista de perguntas ao contador.
🗂️ E o CFOP saiu do código: agora vem do cadastro de naturezas, onde você e o contador mexem sem programador. Sem a linha cadastrada, a pré-nota recusa e explica em vez de chutar um CFOP.
🔧 Por dentro: migration 047 (coluna chave + as duas industrializações, marcadas como "não conferidas pelo contador"); tipoOperacao obrigatório no validarPreNota; nfe.natureza_id passou a ser gravado (a coluna existe desde a 023 e era sempre vazia); o motor do Simples também recebe a natureza (industrialização por ele saía 5101). 62 checagens e 5 mutações em tests/natureza-da-operacao.test.mjs; três testes antigos tiveram a fixture atualizada e um deles trocou a expectativa de 5125 para 5124, com a razão escrita dentro do arquivo.
⚠️ Precisa do Luan: npm run db:migrate (migration 047) + pm2 restart all.
v2.37.840
🚪 O "Várias caixas" agora tem um lugar só — e 🔢 dá pra trocar o número do pedido inteiro de uma tacada.
1 · Um botão a menos. Você viu os dois lado a lado e mandou juntar: "tira o de fora, deixa dentro do
novo — aí fica um lugar só e no Novo Pedido". O botão 📋 Várias caixas saiu do topo da tela. Agora
o caminho é um só: + Novo Pedido → 📋 São várias caixas? Lançar todas de uma vez, que ficou mais
visível (era um link discreto, virou botão azul). Ele continua levando o número e o cliente que você já
digitou, sem redigitar nada.
2 · 🔢 Trocar o número do pedido, nas N caixas de uma vez. Sua pergunta: "lancei 10 caixas que são
10 pedidos, tem como, quando eu for trocar, trocar de todos de uma vez?". Tem. Abra o pedido (clique no
cartão dele) e use 🔢 Trocar o número: digita o número novo uma vez e ele vai em todas as caixas
daquele pedido — junto com o estoque PA e as cargas que ainda não fecharam, como já era na
correção de uma caixa só.
O que ele NÃO faz, de propósito:
• Caixa que já saiu não muda de número (carregada, carregado parcial ou entregue). O romaneio e a nota
daquela carga saíram com o número velho — trocar no sistema depois deixaria o papel do motorista e o pedido
contando histórias diferentes. A tela diz quais ficaram de fora, e quantas mudaram.
• Número que já é de outro cliente é recusado. Dois clientes no mesmo número viram um cartão só na
carteira — seria juntar pedido de gente diferente. Do mesmo cliente pode (é o "esqueci uma caixa e
lancei solta"), e a confirmação avisa antes que elas vão ficar no mesmo pedido.
• Antes de mexer em qualquer coisa ele mostra o resumo e pede confirmação; cancelar não muda nada. A
troca fica registrada na vida de cada pedido.
🔧 Por dentro: trocarNumeroDoPedidoAgrupado no js/01-core.js, reusando o
atualizarNumPedEmCascata que já existia (uma régua só pra cadeia); o botão gêmeo do cabeçalho
saiu do HTML, do js/07-auth.js e do js/86-pedido-lote.js — fiação de botão que não
existe mais já mordeu este repo. +22 checagens e 14 mutações (todas acusadas) em
tests/pedido-lote-prioridade-faturamento.test.mjs. Sem servidor e sem migration — nada
pro Luan.
v2.37.839
🖱️ A busca da caixa no orçamento: agora filtra enquanto você digita, mostra a lista inteira e não arrasta mais a tela.
Três queixas do dono na tela do Novo Orçamento (14/09/2026): "caixas não está buscando do cadastro, estou tentando
colocar mais não consigo" → "apareceu mas não tudo, está demorando muito para aparecer" → "quando eu rolo para
baixo a tela do fundo rola junto, aí eu não consigo chegar no pedido". Eram três coisas diferentes:
1️⃣ Não filtrava enquanto digitava. Os dois campos de caixa do orçamento abriam a lista no clique e ela congelava
— digitar não mexia nela. Quem digitava via a lista parada e concluía, com razão, que não estava buscando. Agora a lista
acompanha cada letra, como o campo de Cliente sempre fez.
2️⃣ Mostrava 5 de 36. O quadro da lista tinha altura fixa — razoável quando ela parava em 8 linhas, apertado demais
depois que o teto caiu. Agora usa o espaço que existe na tela: quase o dobro de linhas por vez.
3️⃣ Rolar a lista arrastava o formulário atrás. A tela do fundo andava junto, o campo saía do lugar e a linha fugia
do dedo. A rolagem agora fica presa dentro da lista.
De quebra, a lista de caixas do cliente passou a ser calculada uma vez em vez de a
cada letra — é a mesma cura que o campo de Cliente levou na v2.37.774/775, e vale o mesmo aqui: com 1.200 caixas no
cadastro, montar a lista caiu de 3,26 ms para 0,003 ms. Só tela: nada mudou no que é gravado.
v2.37.838
📋 O pedido do Sectra com 10 itens agora se lança DE UMA VEZ — e a prioridade alta finalmente vale alguma coisa.
1 · "Cadastrar as 10 caixas ao mesmo tempo". O cliente manda um pedido de 10 itens, o Sectra dá um número
só pros 10 — e aqui você tinha que abrir o "+ Novo Pedido" dez vezes, redigitando o número e o cliente em cada
volta. Agora tem o botão 📋 Várias caixas (do lado do "+ Novo Pedido", e também dentro dele).
Você digita o número do pedido e o cliente UMA vez. Depois vai clicando na caixa, põe a quantidade e a
data, e ela entra na lista embaixo — igual a montar um orçamento. A data e a prioridade ficam preenchidas
pra próxima (no pedido de 10 itens quase sempre é a mesma data), e a mesma caixa pode entrar duas vezes,
com quantidade ou data diferente — que é como o cliente compra. No fim, 🚀 Lançar 4 pedidos e pronto: os 4
nascem com o mesmo número, um do lado do outro no cartão do pedido.
Cada caixa já entra com o que o cadastro dela tem: máquina, roteiro, velocidade e preço (com o reajuste do
cliente, quando tem). Antes de adicionar, a tela mostra numa linha o que ela vai levar — e avisa quando a caixa
não tem preço, quando já tem caixa pronta no estoque e quando essa caixa já está na lista. Se o
número já existir na carteira, ele avisa que as novas entram nesse mesmo pedido.
2 · 🔥 A prioridade ALTA passou a passar na frente. Isto aqui é o conserto de um defeito silencioso: o campo
Prioridade existia desde sempre, mas não mexia em nada — era só um selo colorido no cartão. Quem marcava
"Alta" achava que tinha furado a fila e não tinha furado nada. Agora vale, e vale igual em toda parte: na
carteira, na previsão de entrega e no cronograma das máquinas.
A ordem é esta, nesta sequência: 1º o que já está rodando na máquina (não se reordena o que começou),
2º a ordem que você arrastou em "Reordenar" (sua decisão manda), 3º quem já tem chapa
(material disponível roda antes — não adianta programar máquina sem papel), 4º 🔥 a prioridade e
5º a data de entrega. No lote, a prioridade é de cada caixa, não do pedido inteiro — foi o caso dos
três itens urgentes que você citou. O cartão do pedido mostra 🔥 1 alta no topo.
3 · 🧾 "Imprimir pro faturamento" agora sai também do PEDIDO da carteira. Botão no cartão do pedido e dentro
dele. É a mesma folha do pedido do vendedor e do orçamento — razão social, CNPJ, IE, endereço,
condição de pagamento, prazo, IPI, os itens com preço e peso, o total e a comissão do vendedor
(bloco de USO INTERNO), mais a linha "Faturado por · Data · Nota fiscal nº". As caixas do mesmo número saem num
papel só, com o preço que foi lançado no pedido (não o do cadastro de hoje). E o papel grita
quando alguma caixa está sem preço: faturar 0,00 calado é pior que folha incompleta.
🔧 Por dentro: tela nova em js/86-pedido-lote.js (usa as mesmas funções do "Salvar pedido" — roteiro,
poses, velocidade e preço —, então o pedido nasce idêntico a um lançado na mão); régua única de prioridade
jpPrioPeso no js/01-core.js, usada pelas 4 filas; a folha é a terceira origem da MESMA do
js/09 (o js/87-folha-faturamento-pedido.js só traduz o pedido, não desenha papel nenhum).
76 checagens e 11 mutações em tests/pedido-lote-prioridade-faturamento.test.mjs.
Sem servidor e sem migration — nada pro Luan.
v2.37.837
📅 O 📆 Planejamento agora mostra DIA A DIA, com a barra e os horários — e os dias seguintes deixaram de aparecer vazios.
Seu pedido: "eu quero por dia; quanto tempo eu tenho durante o dia para executar; vi que tenho entrega dia 14 e 15
porém não tem o restante, quero que preenche o dia pra frente; e quero uma barra igual o cronograma com os horários que
tem que começar e terminar — mas isso é previsão somente".
Entrou o quadro 📅 DIA A DIA, embaixo das semanas. Para cada dia útil das 2 semanas: uma raia por máquina
com as barras no horário certo (régua de 2 em 2 horas, do início do turno até o fim, rabo da noite incluído), e no
cabeçalho ocupado X h de Y h · livre Z h — que é a resposta de "quanto tempo eu tenho hoje". Passa o mouse
na barra: cliente, caixa, quantidade, começa e termina, e a data de entrega. Clica: abre o pedido.
🔍 Por que os dias 16, 17, 18 apareciam vazios — e o conserto. O cronograma só planeja quem já tem
programação ou material (chapa lançada). Isso está certo para ele, que é o plano de quem vai rodar hoje — mas
49 dos seus pedidos abertos estão em "esperando programação", e por isso sumiam da conta. Agora a previsão inclui
esses também, e eles entram com a barra listrada: dá pra ver a carga que vem sem confundir com o que já tem papel.
Na sua carteira, os dias saíram de 2 preenchidos para as duas semanas inteiras (hoje 48,7 h ocupadas de
52,8 h, amanhã 46,8 h, depois 37,1 h…).
Quem distribui continua sendo o cronograma — a mesma fila, os mesmos turnos, o mesmo fatiamento de pedido grande.
Esta tela só desenha: duas agendas que discordam seria pior que nenhuma. E está escrito em cima que é
PREVISÃO: quem manda na fábrica é o 🏭 Cronograma.
🔧 Por dentro: cronPlanejar(ds, opts) (js/21) passou a aceitar uma lista de quem chama — sem o parâmetro
ele é byte-idêntico, o cronograma não mudou nada; previsaoDiaria + quadroDias no
js/83-planejamento-semanal.js, posicionando a barra pela régua do próprio cronograma
(cronClampShow). 81 checagens e 29 mutações em tests/planejamento-semanal.test.mjs e
20 e 6 em tests/cronograma-acha-a-caixa-como-o-resto.test.mjs.
Sem servidor e sem migration — nada pro Luan.
v2.37.836
📦 O 📆 Planejamento passou a mostrar o papel da semana separado por ONDA e por GRAMATURA.
Seu pedido: "eu quero planejamento por onda separada e por gramatura, assim fica mais organizado".
Dentro de cada semana, embaixo do quadro das máquinas, entrou 📦 O PAPEL DESTA SEMANA. Em cima, uma
faixa por onda (ONDA B, ONDA BB) com quantas gramaturas ela tem, as caixas e os quilos; embaixo,
uma linha para cada gramatura, com os pedidos, as caixas e o papel em kg. A ordem é a que a onduladeira
roda: primeiro a onda, dentro dela a gramatura do menor pro maior.
Medido na sua carteira agora: esta semana são 203.215 cx e 50.396 kg — a ONDA B com 5 gramaturas
(154.657 cx) e a BB com 2 (17.558 cx). Só a B 384 são 133.657 cx em 15 pedidos.
Três cuidados que valem saber: conta a etapa de corte, uma vez só — é ali que a chapa entra, e
somar o acabamento diria o dobro de papel; o peso sai do cadastro da caixa, e caixa sem peso aparece nas
caixas mas fica de fora dos quilos (com o aviso), em vez de ter o peso chutado; e caixa sem onda ou sem
gramatura no cadastro ganha linha própria no fim — papel é compra, e número de compra não se
adivinha. Hoje são 4 pedidos nessa situação nesta semana.
🔧 Por dentro: papelDoPedido + quadroPapel no js/83-planejamento-semanal.js,
lendo onda, gramatura e pesoKg do cadastro pelo casamento do js/01.
67 checagens e 24 mutações em tests/planejamento-semanal.test.mjs.
Sem servidor e sem migration — nada pro Luan.
v2.37.835
🔧 Os 23 pedidos que estavam "sem máquina" no 📆 Planejamento — 15 resolvidos, e os 8 que sobraram agora dizem o que falta.
Você abriu a aba nova e viu o quadro amarelo: "20 etapas que não entram na conta das máquinas". Fui atrás de um por um.
Eram três problemas diferentes com a mesma cara:
1 · Cinco eram defeito do sistema, não do cadastro. KININO 10, 20, 22 e 39 e a QLX 07 POLICOLOR apareciam
com a máquina certa na Carteira e no tablet e sem máquina nenhuma no cronograma. Motivo: o cronograma
procurava a caixa exigindo o código idêntico, e o resto do sistema já aceita que "KININO 22" é a "CX 22"
do KININO. Agora ele pergunta do mesmo jeito que todo mundo. 40.000 caixas voltaram pra conta.
Conferi nos 360 pedidos do banco antes de mexer: nenhum trocou de caixa, 20 passaram a achar a que já existia.
2 · Dez eram cadastro de caixa sem a máquina — e as caixas já tinham rodado, de 1 a 8 vezes, todas na
Máq. B Slotter. Com a sua autorização, gravei a Slotter no cadastro das 5 caixas (NACON 19 GRAN MESTRI-B,
FK GRUPO 44959 e 30766, THREE LIFE LAB 01 e TCHETTO 01 MOLHO REFOGADO). Resolve os 10 pedidos e todo pedido
futuro dessas caixas. Só o campo da máquina mudou — conferi campo a campo depois de gravar, e tem cópia de
segurança do cadastro inteiro de antes.
3 · Oito continuam de fora, e agora a tela diz por quê. São caixas que não casam com o cadastro
(JESSE "06 FRITOS B" × "CX 06 FRITO", FORTYS, VIVIMAR, TANGARA e a TATYANA, que não tem caixa cadastrada).
Aí não é conta: alguém tem que dizer qual é qual. O quadro amarelo ganhou a coluna "Já rodou em" — quando a
caixa tem histórico, ele mostra a máquina e quantas vezes — e a linha da máquina mostra
"+ X h esperando cadastro", pra você ver o tamanho do que ainda está fora sem que isso entre na conta como
se estivesse resolvido.
🧾 E o "Imprimir pro faturamento" entrou também dentro do Ver/Enviar orçamento, que foi onde você apontou.
É o mesmo botão e a mesma folha do cartão da lista (a do pedido do vendedor) — não um papel novo parecido,
que era o caminho fácil e o que faz duas folhas discordarem depois. Aparece em orçamento aceito ou
convertido, a mesma regra do outro botão.
🔧 Por dentro: cronCaixaDoPedido (js/21) passou a perguntar ao fpCaixaDoPedido (js/01), com o
casamento exato de reserva; maquinaPeloHistorico + a coluna e o "esperando cadastro" no
js/83-planejamento-semanal.js; o botão do modal chama o orcImprimirFaturamento (js/85) já
existente. 18 checagens e 5 mutações em tests/cronograma-acha-a-caixa-como-o-resto.test.mjs,
58 e 21 em tests/planejamento-semanal.test.mjs e 12 e 6 em
tests/faturamento-uma-folha-so.test.mjs. Sem servidor e sem migration — nada pro Luan.
v2.37.834
🧾 Na folha de faturamento, o "Prazo padrão" parou de acusar cadastro que está completo.
O dono testou a folha nova no orçamento nº 0048 da GAIOTO — negociado em 7 DIAS — e circulou o campo:
o papel dizia "Prazo padrão: não cadastrado · do cadastro do cliente", e o cadastro da GAIOTO
tem condição de pagamento (7/14/21 Dias).
Não faltava nada no cadastro. Nesta casa quem manda no vencimento é a condição de pagamento — ela é
que carrega o parcelamento —, e o campo "prazo padrão" é só a reserva de quem não tem condição nenhuma.
Cliente com condição tem esse campo vazio de propósito. O papel é que estava lendo isso como buraco.
Agora a célula diz quem manda: sem prazo próprio e com condição, sai "pela condição de pagamento";
com os dois preenchidos, sai o prazo e o aviso de que a condição é que vale; e "não cadastrado" ficou
só pra quem não tem nenhum dos dois — que é quando falta de verdade.
🔧 Por dentro: a célula do prazo no pvPedidoHTML
(js/09-logistica.js) passou a seguir a MESMA hierarquia que já valia em três lugares — a baixa
(js/01), o espelho da pré-nota (js/64) e a conferência de crédito
(cliCreditoSituacao, js/08). Vale nas duas folhas (pedido do vendedor e orçamento vendido):
o papel é um só e o defeito era do papel. 5 checagens novas e a 13ª mutação em
tests/folha-faturamento-orcamento.test.mjs. Sem servidor e sem migration — nada pro Luan.
v2.37.833
📜 A lista de busca passou a mostrar TODOS — antes parava em 8 e o resto sumia calado.
Queixa do dono (14/09/2026): "tem cliente que não aparece todas as caixas dele, no caso deles tem que aparecer
tudo — e se não couber, tenha rolagem pra chegar até a caixa, ou se souber, digitar e vai aparecendo".
Estava certo: num cliente de 30 caixas, a lista mostrava 8 e as outras 22 nem existiam na tela,
sem nenhum aviso de que faltava coisa. Lista que mente dizendo que acabou é pior que lista comprida.
Agora quem casa entra. A lista abre do tamanho que couber na tela, com rolagem pra alcançar o
resto, e digitar continua estreitando. Vale pros dois campos do pedido, pros três do orçamento e pros ~30
campos de busca do resto da casa.
O teto de 8 tinha vindo da v2.37.776, por medo do tablet — e era medo mal
colocado: o que engasgava o iPad era a lista nativa do navegador, não o nosso desenho. Medido agora, no
motor de verdade: desenhar 400 linhas custa menos de 1 ms. De quebra, o desenho ficou 5× mais barato
(7,7 → 1,5 ms com 180 clientes, por tecla), porque a caixa passou a ouvir o clique uma vez só em vez de
uma vez por linha — agora o custo não cresce mais com o tamanho da lista. A lista também escolhe sozinha
abrir pra cima quando o campo está no pé da tela, e nunca fica mais de uma aberta ao mesmo tempo.
v2.37.832
🧾 O "Imprimir pro faturamento" agora está no ORÇAMENTO também — a mesma folha, com o que foi negociado.
Pedido do dono (14/09/2026), com as duas fotos lado a lado: "eu quero esse imprimir para o faturamento os pedido
que vendo do orçamento! tbm para mandar para o faturamento como foi negociado!" — e logo depois:
"tem que ser igual, com as mesmas informações".
O botão 🧾 Imprimir pro faturamento apareceu no cartão de todo orçamento aceito ou convertido.
É a mesma folha do pedido do vendedor, sem uma vírgula de diferença no desenho: razão social, CNPJ, IE,
endereço e CEP do cadastro, os itens com quantidade, preço unitário de 3 casas, total e peso, a comissão do
vendedor e a linha no pé pra anotar quem faturou, quando e o nº da nota.
O que muda é de onde vêm os números: do orçamento, como foi negociado. O preço é o que o cliente aprovou,
a condição de pagamento é a do orçamento (com as parcelas: "3 × de R$ 2.045,39 — 7/14/21 dias"), o IPI é o do
orçamento e a medida da caixa é a que foi vendida — mesmo que o cadastro tenha mudado depois. Embaixo do total sai
"+ IPI ... + ferramenta à parte ... = total negociado", que é o número que o cliente aprovou.
E a folha não cala o que está diferente: se o IPI do orçamento não é o do cadastro do cliente hoje, sai um
aviso em vermelho ao lado ("o cadastro do cliente hoje é 15 %") — quem fatura precisa reparar nisso antes de
emitir a nota, não depois.
Venda parcial sai certa: o cliente que fechou 2 das 7 caixas recebe uma folha com as 2 — e o papel escreve,
no rodapé, quais ficaram fora e por quê ("em aberto" × "o cliente não quis"), com a frase
"não fature o que não está nesta folha". Orçamento aceito de uma vez continua saindo inteiro.
🔧 Por dentro: js/85-folha-faturamento-orc.js não desenha folha
nenhuma — traduz o orçamento e chama o pvPedidoHTML/pvPedidoCSS do
js/09-logistica.js, que ganhou um folha: com os poucos textos que a origem diz de outro
jeito (duas folhas parecidas divergiriam na primeira correção — §9.13). Os totais saem do
JPNotaOrc.totais (js/48), a mesma régua do papel que foi pro cliente, rodando só sobre as caixas
vendidas. 45 checagens e 12 mutações em tests/folha-faturamento-orcamento.test.mjs, mais a prova
de que a folha do pedido do vendedor saiu idêntica em 8 cenários. Sem servidor e sem migration — nada
pro Luan.
v2.37.831
🔎 A busca de cliente ficou igual em TODA tela — e a "Caixa do cliente" virou campo de digitar.
Pedido do dono (14/09/2026), com as duas fotos lado a lado: "modelo de busca de cliente no cadastro de pedido
igual a do orçamento", "esses todos os campos de busca quero que deixa igual para tudo",
"caixa do cliente também", "nome da caixa e embaixo gramatura usada, para ficar padrão".
No "+ Novo Pedido": o campo Cliente tinha a lista do navegador — os 156 clientes de uma vez, sem cidade e
sem marca de inativo. Agora é a mesma lista do Orçamento: nome em cima, cidade/UF embaixo, os 8 mais
parecidos, e quem está inativo aparece marcado 🔴. Dá pra andar com ↑ ↓ e escolher no Enter.
Caixa do cliente: era um menu de rolar com 30 linhas e nenhum jeito de digitar. Virou campo de busca com o
mesmo desenho — o nome da caixa em cima e a gramatura usada embaixo ("03 KIT QUEIJO ARTESANAL-B · Onda B ·
411 g/m²"). Acha também pelo nome de fantasia: quem lembra "molho refogado" e não o código, acha.
E em todo o resto: todo campo de buscar da casa passou a usar essa mesma lista, sem exceção — fornecedor
no almoxarifado, produto e nota no lançamento de custos, cliente no desenvolvimento e no laudo, transportadora e
placa na expedição, função no RH, operador no ponto. Eram cerca de 30 campos em 9 telas, cada um com a lista do
navegador.
Por que mexer nisso: a lista do navegador é a que engasgava no iPad com a
carteira cheia (a queixa de 10/09, "demora muito pra aparecer o cliente"). A cura já existia — ficou presa em três
campos do Orçamento desde a v2.37.776. Agora a mecânica mora num lugar só e vale pra todos. Só tela: nada mudou no
que é gravado, nem no servidor.
v2.37.830
📆 Aba nova em Produção: Planejamento — as próximas 2 semanas contra a capacidade de cada máquina.
Pedido do dono (14/09/2026): "quero fazer um planejamento semanal do que temos para entrega dentro de 2 semanas,
o que tem essa semana e o que tem para semana que vem, dentro da capacidade e da velocidade de cada máquina".
A tela mostra, por máquina, quantas horas o que está prometido vai tomar × quantas horas ela tem na semana,
com a ocupação em % e quanto sobra (ou quanto falta, em horas e em dias).
O atrasado entra na conta desta semana — um pedido que venceu continua ocupando a máquina hoje, e mostrar
a semana sem ele diria "cabe" para o que não cabe. Na carteira de 14/09/2026 eram 23 pedidos vencidos, e só na
Coladeira davam 38 h: com os da semana, 61,8 h contra 44 h de capacidade.
Nenhuma conta nova: a velocidade é a do cadastro da caixa naquela máquina (a mesma do Mural, do tablet e do
cronograma), o tempo é quantidade que falta ÷ velocidade mais o setup, e a capacidade é o turno cadastrado
de cada máquina × os dias úteis que ainda existem na semana. Pedido já pronto esperando caminhão não ocupa máquina,
e o que já foi produzido desconta.
Quem não dá pra planejar aparece em vez de sumir: pedido sem máquina escolhida
ou sem velocidade fica num quadro próprio, com o motivo e o caminho pra resolver — inclusive quando o pedido está
sem máquina mas a caixa tem uma cadastrada. Eram 20 etapas / 128.520 cx assim em 14/09/2026. Só leitura: a tela
não grava, não reprograma e não muda status.
v2.37.829
⏱ O operador também vê a hora prevista de término, debaixo da velocidade.
Pedido do dono (14/09/2026): a mesma linha do Mural na tela do tablet. Na caixa do sensor, logo abaixo do
"⚡ 3.900 cx/h · meta 3.000", aparece "⏱ termina ~14:47 · faltam 10.750 cx · 2h45 no ritmo de agora".
Usa o que falta do pedido e o ritmo medido pelo sensor; sem ritmo ainda, a meta da máquina, dizendo "na meta".
Só com a produção rodando.
A conta é UMA só, compartilhada pelo Mural e pelo tablet: os dois mostram a
mesma hora pro mesmo pedido. Só tela, sem servidor.
v2.37.828
⏱ Mural: o cartão diz a que horas o pedido termina, no ritmo de agora.
Pedido do dono (14/09/2026): "tempo estimado de término na produção, em cima da velocidade da máquina".
Logo abaixo da barra do pedido, a máquina RODANDO ganhou a linha "⏱ termina ~14:47 · faltam 11.552 cx · 2h47
no ritmo de agora". A conta é o que falta dividido pelo ritmo que o cartão já mostra — o do sensor quando a
máquina lê por ele, senão o do apontamento. Sem ritmo ainda, usa a meta e diz "na meta". Se cair no dia seguinte,
escreve "amanhã". Quantidade atingida, avisa.
Só com a máquina rodando: em parada ou pausa o ritmo é de antes e a hora seria
mentira. A conta é simples de propósito, não desconta almoço nem fim de turno — é "no ritmo de agora".
v2.37.827
📦 No orçamento, digitar comprimento, largura e altura já diz quantas caixas
vão no palete — igual ao cadastro de caixa. Pedido do dono em 13/09/2026:
"eu preciso saber quantos paletes eu vou usar".
🚨 O lastro vinha CHUMBADO na configuração: caixa pequena e caixa grande
recebiam o mesmo número, então mudar a medida não mudava o total de paletes.
Agora ele sai do mesmo motor do cadastro — o que arruma a caixa dobrada no palete e
conta quantos pacotes cabem na base. Aqui ele roda só pra dar o número: no
orçamento não entra desenho nenhum.
✅ Conferido contra a própria tela do cadastro: chapa 531 × 176 mm,
onda B, amarrado 25, palete 1000×1200 → lastro 32 · 7 camadas ·
5.600 caixas por palete — o mesmo número nos dois lugares. Se um dia divergirem,
é porque alguém fez uma segunda conta.
⚙️ Orçamento ▶ Configurações ganhou o bloco do palete:
peças por amarrado, altura máx., altura do palete vazio, comprimento e largura do
palete, desconto de aba e overhang. O "Pacotes no lastro" virou opcional
(vazio = calculado pela medida); preencha só pra forçar um número fixo.
⚠️ O que você digitar em "Caixas por palete" continua mandando — o
padrão nunca escreve por cima. Corte e vinco sem fechamento conta 1 espessura (sai
plano); com cola ou grampo conta 2, como a maleta. E sem medida, ou com palete baixo demais,
ele não inventa palete: fica vazio, como antes.
v2.37.826
🧪 A amostra do Desenvolvimento virava orçamento zerado. Puxando a solicitação
nº 0047 · TANGARA no 💰 Fazer orçamento, vinham o cliente e as medidas —
e mais nada. A caixa, que é maleta, entrava na lista assim:
Corte e Vinco · chapa 30×30 mm · 0 un × R$ 0,000, com 0,0 kg e
sem mínimo.
🔎 Era uma causa só, com três estragos. A chapa não era encontrada. E chapa não
encontrada derruba tudo junto: sem a onda o orçamento deduz corte e vinco (e aí a
"chapa" de 30×30 mm é só o refile); sem a gramatura o peso dá 0 kg; sem o
R$/kg o preço sai R$ 0,000. Um item errado no lugar de um aviso.
🧱 Por que não era encontrada. O Desenvolvimento mandava a chapa por dois caminhos que
o navegador não conhece: o número interno do banco (que não é o número da lista de
chapas da tela) e o rótulo escrito — B 384 · B, que é nome · onda, não o
código. E o código dessa chapa, no cadastro, é M110M110M110-B (a composição do papel):
nem parecido com o rótulo. Procurando só pelo código, nunca ia achar.
📊 Não era um caso: era todos. Conferido no sistema de verdade — das 15 caixas de
amostra já registradas, 15 chegavam sem a chapa. E nenhuma das 26 chapas do
cadastro tem o código igual ao nome, então o caminho antigo nunca teve chance.
✅ Agora entra completa. A mesma nº 0047 vira 📦 Maleta Normal (B), chapa
1.262 × 489 mm, 0,237 kg por caixa e R$ 2,085/cx — com a gramatura (384 g), a
coluna (5 kgf) e o mínimo da chapa no lugar. Nas 15, as 15 acham a chapa.
🩹 As solicitações que já estão na fila se curam sozinhas. A nº 0045, a 0046 e a 0047 não
precisam ser refeitas no Desenvolvimento: é só abrir o 💰 Fazer orçamento de novo.
📐 O modelo da caixa viaja junto. Meia maleta e aba transpassada deixam de
virar maleta inteira no caminho — a meia cobrava uma aba a mais e a transpassada
meia aba a menos (esta última, preço abaixo do custo).
🔢 Sem quantidade, a tela avisa. Amostra não tem quantidade — ninguém compra amostra por
lote. Antes o item entrava 0 un × R$ 0,000 sem dizer por quê; agora pede: "a amostra não
traz quantidade, digite a do orçamento".
🛡️ Pra não repetir: 41 checagens em
tests/orcamento-da-amostra-chapa.test.mjs, com a chapa e a solicitação de
produção — e as mutações reproduzem exatamente o print do dono (corte e vinco,
30×30 mm, R$ 0,000) quando o conserto é desligado.
🔧 Por dentro: orcChapaDaSolicitacao + orcOndaDoRotulo +
orcEstiloDoModelo (js/08-cadastros.js) — a tradução modelo→estilo, que estava
escrita à mão dentro do orcPreencherDaCaixa, virou régua única e agora atende
o cadastro e a solicitação. No servidor, o abrirSolicitacaoDeOrcamento
(api/src/routes/desenvolvimento.js) passou a resolver a chapa antes de gravar:
manda o legacy_id, o código, a onda, a gramatura, a coluna e o
modelo. 🧰 O Luan precisa dar pm2 restart pra metade do servidor valer
nas amostras NOVAS — o que já está na fila a tela resolve sozinha. Sem migration.
v2.37.825
🔒 Clicar fora não fecha mais a janela. Um clique errado ao lado do
Editar Orçamento jogava a janela fora e levava junto tudo o que estava digitado —
item montado, medidas, R$/kg, o motivo da revisão — sem perguntar nada. E a janela é
grande: a borda fica logo ali do lado do mouse.
✅ Agora o fundo não fecha. Saídas continuam três: o ✕, os botões
Cancelar/Fechar, e o Esc. Vale pras 55 janelas do sistema, não só o
orçamento — cadastro de caixa, pedido, cliente, todas.
👆 E ele responde ao clique, em vez de fingir que nada aconteceu: a janela treme de
leve e, na primeira vez, aparece o aviso "clicar fora não fecha mais — use o ✕, o
Cancelar, ou aperte Esc". Só na primeira: repetir a cada clique viraria barulho.
📷 Uma exceção de propósito: a foto ampliada continua fechando no clique. Ali não
há nada pra perder, é o gesto que todo mundo espera — e ela não tem ✕, então sem a
exceção ficaria presa na tela.
🔑 O cuidado que quase passou batido: o Esc já era da lista de sugestão (aquela
que aparece quando você digita o nome do cliente). Sem uma trava, apertar Esc pra tirar a
sugestão fecharia o orçamento inteiro junto — seria trocar um jeito de perder trabalho
por outro. Agora o Esc fecha a sugestão primeiro; o segundo Esc é que fecha a janela.
Com duas janelas abertas, ele fecha só a de cima.
🛡️ Pra não repetir: 14 checagens e 7 de 7 mutações acusadas em
tests/janela-nao-fecha-no-clique-fora.test.mjs — inclusive "o clique no fundo volta a
fechar tudo", "a foto ampliada fica presa na tela" e "o Esc deixa de sair da frente da sugestão".
Conferido no navegador, no modal de verdade: clicou fora 3× e continuou aberto, Esc fechou;
com a sugestão do cliente aberta, o 1º Esc tirou só a sugestão.
🔧 Por dentro: o bg.onclick de .modal-bg em js/01-core.js parou de
chamar o fecharModal e passou a chamar jpModalAvisaQueNaoFecha; a
exceção mora no JP_MODAL_FECHA_NO_FUNDO; e um keydown global fecha a
janela de cima (pelo z-index) depois de conferir que não há
.jp-sug-lista aberta. Sem servidor e sem migration — nada pro Luan.
v2.37.821
🔇 Renomeou a caixa e a tela ficava MUDA. Desde 09/09 dava pra renomear uma caixa e não
receber aviso nenhum sobre os pedidos. O aviso existia só pro caso de sucesso: se nenhum
pedido fosse regravado, silêncio. E silêncio é a pior resposta — quem não recebe aviso tenta de
novo, ou desiste achando que o sistema quebrou.
✅ Agora fala nos três casos. Regravou: "3 pedidos da carteira passaram a se chamar
CX 04". Não regravou e a caixa não é usada: "Nenhum pedido da carteira usa esta caixa — o
nome novo vale daqui pra frente".
🔑 E o terceiro caso, que era o confuso: nenhum pedido regravado não quer dizer que não
pegou. A coluna Produto/Cód. mostra o nome do cadastro direto, resolvendo o pedido por
apelido, por prefixo "CX " e até pelo nome do cliente dentro do código (o caso
KININO 22 × CX 22). Nesses o nome novo já aparece na tela sem regravar nada — e agora
o aviso diz isso: "a coluna Produto/Cód. de 5 pedidos já mostra CX 22 direto do cadastro".
🧹 Uma régua só. O texto estava copiado nas duas portas (cadastro de caixa e
micro/cartão): consertar uma deixava a outra para trás. As duas passam a chamar a mesma função.
✂️ E o campo da Referência cabia MENOS que o próprio cadastro. O limite era 20 letras
e "TIPO 02 SEM IMPRESSAO" tem 21 — não dava pra digitar um nome que já está cadastrado:
o campo cortava calado na última letra. Subiu pra 40 nas duas telas. O banco é
TEXT e a API não valida tamanho, então o 20 era teto inventado só na tela.
🛡️ Pra não repetir: tests/nome-do-pedido-segue-a-caixa.test.mjs volta a passar
inteiro — ele cobrava as três frases e o tamanho do campo, e falhava desde 09/09. Conferido também
no navegador, na página de verdade: as quatro mensagens saem certas, com singular e plural.
🔧 Por dentro: cxAvisarRenomeacao(n, cx) em js/08-cadastros.js, chamada por
cxSalvar e micSalvar no lugar do if(_n) toast(...). O caso
"a tela já mostra" sai do fpCaixaDoPedido (js/01), que casa muito mais que o
contarVinculosCaixa — é justamente essa diferença que criava o silêncio.
Sem servidor e sem migration — nada pro Luan.
v2.37.820
💰 Reabrir um orçamento parou de mudar o preço que o cliente já recebeu.
Você reabria um item pra corrigir a referência e o campo R$/kg já aparecia com o
número de hoje — e o botão 💾 Atualizar item grava o que está no campo.
Ou seja: arrumar uma letra da referência gravava um preço novo.
🔎 Medido: o R$/kg gravado 4,497 virava 4,800 e o unitário
6,745 virava 7,200. Num item de 20.000 caixas, o papel que o cliente
recebeu — R$ 134.900,00 — passava a valer R$ 144.000,00:
R$ 9.100,00 a mais, sem ninguém pedir.
🔑 O próprio aviso da tela já prometia que isso não acontecia. A frase
“o preço gravado continua valendo até você mexer” existe desde a v2.37.600 — ela
só aparecia depois de o campo já ter sido trocado. Agora ela é verdade.
⚠️ Uma coisa mudou de propósito: mexer na quantidade continua trazendo o
preço sugerido de hoje — o acerto se dilui em mais ou menos caixa, então o R$/kg muda
com ela de verdade. O que não acontece mais é o campo ser reescrito enquanto a
quantidade é a mesma que foi gravada.
🧮 E o preço sugerido de hoje continua à vista, do lado do que você cobra (a
v2.37.799): quando você quiser adotar, é o “usar preço sugerido” — agora por
escolha sua, não por conta própria.
🔧 Por dentro: ORC_RSKG_SALVO_MANDA + ORC_RSKG_SALVO_QTD
(js/08), ligados pelo orcEditarItem e desligados em 6 pontos — os 3 que já
zeravam o modo do R$/kg (abrir o modal, gravar o item, cancelar a edição) e os 3 de
adotar um preço (sugerido, assistente, programa), porque aí você decidiu outro; a
ressincronização do orcRecalcItem passou a pular enquanto a quantidade não
muda. 22 checagens e 4 mutações em
tests/orcamento-reabrir-nao-muda-o-preco.test.mjs, com o controle contra a
v2.37.818 acusando o defeito. Sem servidor, sem Luan.
v2.37.819
📦 A caixa de Corte e Vinco com apelido parou de virar caixa duplicada no cadastro.
Ao puxar a caixa no campo de C&V, a referência do item vira código + apelido —
“CX 22 KININO”. Dali em diante ninguém achava a caixa, porque todo mundo procurava pelo
código exato. Duas consequências: o preço perdia a Coladeira de uma caixa colada,
e ao virar pedido nascia outra caixa no cadastro.
🔎 Não é caso raro: 11 das 13 caixas de C&V que entram nesse campo têm
apelido — e na prática o apelido guarda o nome do cliente (“CX 22 KININO”, “03 TEMPERO
TCHETTO”).
🔑 E o elo certo já existia. O item guarda o número de identidade da caixa desde
15 de julho — e ele era lido num lugar só: pra reabrir o formulário. Agora os quatro
pontos que decidem preço e criam pedido leem ele primeiro, e a busca por código fica de
reserva pros itens antigos.
🛡️ Sempre dentro do mesmo cliente. Identidade apontando pra caixa de outro cliente é
recusada — juntar caixa de clientes diferentes é o erro mais caro que este sistema já
teve.
🧮 O “preço pelo custo” voltou a somar os insumos. Ele lia um campo que o motor
nunca devolveu: grampo, arame, paletes e cola ficavam de fora da conta — com os nomes
deles listados ali do lado, o que fazia parecer que estavam contados. Com os seis insumos
reais, são R$ 0,16 por caixa que não entravam. Não muda o preço do cliente (hoje a
venda é por quilo); muda o custo líquido e a margem que o gestor lê pra decidir.
🔒 E o orçamento que abre vazio agora diz por quê. Quando o servidor recusa a lista por
falta de permissão, o sistema apaga a lista — o que está certo, porque aparelho
compartilhado não pode guardar o que era de outro login. Só que a tela escrevia “Nenhum
orçamento ainda”, a mesma frase de quem de fato não tem nenhum, e a pessoa ficava
procurando o que sumiu. Agora ela diz que a lista existe e o que falta é o acesso.
🤫 Sem aviso pulando na tela: pra quem não tem essa tela, a recusa é esperada, e
avisar a cada consulta viraria barulho. O recado aparece só dentro da tela vazia.
v2.37.818
🧾 O custo passou a dizer o que ficou de fora — e a chapa parou de chutar. O rodapé do
Custo completo promete, em letra miúda, que “o que estiver não cadastrado está FORA do
custo”. Três coisas ficavam de fora sem aparecer.
🔎 1 · Máquina sem velocidade. Sem velocidade cadastrada, entra só o acerto — o
tempo de rodar as caixas fica fora do custo. É o caso de toda caixa de Corte e
Vinco. A linha saía normal, com o aviso escondido no meio do texto cinza. Agora ganha uma
nota em âmbar dizendo quantas caixas não foram custeadas.
🛡️ E não é riscada: o acerto é custo real que entrou. Riscar seria mentir pro
outro lado.
🔎 2 · Insumo que o motor recusou. Quando falta a paletização ou o fechamento da caixa,
o motor recusa o insumo e explica por quê — e essa explicação nunca chegava na
tela. Pior: quando nenhum entrava, a tela dizia “nenhum insumo cadastrado”, que é
falso (há seis) e mandava o gestor pra aba errada. Agora o recusado aparece
riscado, com o motivo.
🔎 3 · O Financeiro que ainda não chegou. As listas de folha e custos fixos nasciam
vazias e só chegavam 3,4 segundos depois do login — e a sessão inteira, se a API
falhasse. Nessa janela o custo-hora saía a 31% do real (R$ 45,23/h contra R$ 144,68) e o
orçamento escrevia “custo-hora calculado”, sem marca nenhuma. Agora ele semeia do último
valor conhecido no boot, como o cadastro de máquinas já fazia.
✂️ 4 · E a chapa do pedido reprogramado. O TANGARA 05 FLOPS 92 dizia “Lançada 2.200 ·
Usada 7.152 · faltaram 4.952 · +213%”. Nada disso: a chapa foi lançada em duas levas
(5.000 + 2.200 = 7.200) contra 7.152 usadas — sobraram 48. O campo guarda o
estado de hoje, não um livro, então num pedido reprogramado ele tem só a última leva.
✅ O sistema não guarda o total lançado em lugar nenhum — então aqui ele não
inventa: quando sabe que a quantidade não fecha, escreve “—” com o motivo, igual já
faz com a chapa usada. O sinal que usamos já existia e ninguém lia: o alarme de
quantidade anômala que a v2.31.36 acende quando o pedido produz mais de 50% acima do pedido.
🧪 Testes: precalculo-diz-o-que-ficou-de-fora e
chapa-lancada-nao-chuta.
v2.37.817
🛡️ Uma trava nova no envio: “este push atropela alguém?” Ontem, publicando a
v2.37.816, a main andou cinco vezes enquanto o merge era resolvido. Duas coisas
quase foram pro ar sem ninguém ver.
🔎 A primeira. Um merge feito contra uma versão da main que tinha envelhecido
apagava 73 linhas já publicadas — o filtro por cliente e período do
📉 Abaixo do preço sumiria inteiro, poucas horas depois de entrar no ar. E
nenhum teste pegaria: o código continua válido, só fica sem a função. É o
mesmo perfil do CORS que quase se desfez em 09/09.
🔢 A segunda. Uma entrada do histórico caiu em cima de um número que a main já
tinha publicado com outro assunto. A v2.37.806 seria, ao mesmo tempo, o filtro do
Abaixo do preço (no ar) e uma correção do Pós-cálculo. Número com dois donos é
histórico perdido — já aconteceu três vezes nesta casa.
⚠️ A trava que existia não pegava nenhuma das duas. Ela compara só o número
final com a main: 816 é maior que 806, então passava batido — o número
repetido estava no meio da faixa. E ela roda na hora de numerar, cedo
demais: a main ainda ia andar mais três vezes até o envio.
✅ Agora a conferência é na hora do ENVIO, que é quando dói, e só quando o
destino é a main — quem trabalha na sua própria cópia não é atrapalhado. Ela
responde três perguntas: some alguma linha que já está no ar?, tem número
repetido? e as marcas de versão estão todas alinhadas? (desalinhada é o
loop de “Atualizar” na fábrica). Leva 1 segundo.
🥊 E ela apanhou antes de entrar. Seis frentes tentaram derrubá-la e
conseguiram: a versão inicial deixava passar justamente o caso que a motivou,
porque o conselho que ela mesma imprimia a desarmava. Foi reescrita e agora pega
os três ataques — inclusive apagar só linhas curtas, do tamanho de um
return; de segurança. Também parou de gritar à toa: mexer num campo
de cadastro ou corrigir o português de uma entrada antiga não travam mais nada.
Conferida contra os 40 últimos envios reais: nenhum seria bloqueado.
🔧 Dois consertos de brinde. A conferência da API rodava sobre o commit errado
(olhava a cópia aberta na tela, não o que estava subindo), e a trava passou a usar a
versão da main que o servidor acabou de informar, em vez da última que a máquina
tinha baixado. Pra conferir na mão: npm run check:versao.
🧰 Nada de novo pro Luan. É só no envio, aqui na máquina.
v2.37.816
📊 No Pós-cálculo, o “orçado” e o “real” contavam quantidades de caixa diferentes — e a
diferença não batia. No pedido 24126 da GRS, a linha dizia 17.808 cx, custo
orçado R$ 32.724,66 e custo real R$ 26.243,93. Quem subtrai os dois vê
R$ 6.480,73 de economia. Não existiu.
🔎 Por quê. Aquele orçamento tinha sido feito pra 22.000 caixas; a fábrica
entregou 17.808. O custo real já vinha trazido pras 17.808 (desde a v2.37.612),
mas o custo orçado continuava sendo o das 22.000. Dois números de tamanhos diferentes,
lado a lado, na mesma linha, com a coluna Qtd dizendo 17.808.
🧮 Os R$ 6.480,73, abertos: R$ 6.235,54 é caixa que nunca existiu
(4.192 × R$ 1,4875) e só R$ 245,19 é diferença de verdade — que é, à vírgula, a
máquina (R$ 456,32 orçados pras 17.808 contra R$ 211,14 apontados). Por caixa, o pedido
saiu R$ 1,4737 contra R$ 1,4875 orçados: 0,9% mais barato, não 20%.
✅ Agora a coluna “Custo orçado” já vem nas caixas que saíram, e embaixo dela fica
escrito pra quantas o orçamento tinha sido feito — o total do orçamento não se apaga
(REGRA ZERO). Quando as duas quantidades batem, nada muda na tela.
📦 E o detalhe do pedido explica a conta, com os R$ separados entre “caixa que não
existiu” e “variação de verdade”. Mesma explicação no PDF.
⚠️ O que continua valendo. A margem sempre esteve certa (no 24126: −10,2%
previsto × −9,2% real) porque ela é por caixa e a quantidade se cancela — quem mentia
era só a coluna de reais. E segue valendo o aviso de sempre: só a máquina é medida.
Papel, tinta, insumos, frete e ferramental entram pelo mesmo R$/cx dos dois lados
(no 24126, R$ 1,4619 de R$ 1,4875 — 98,3% do custo), então a diferença entre orçado e
real só enxerga máquina e quantidade. Se o papel veio mais caro, esta tela não vê.
🕐 As horas da tabela de máquina não foram mexidas: continuam as do orçamento, nas
22.000 — o acerto da máquina não encolhe junto com a tiragem, e prorratear isso seria
trocar um número errado por outro. A tela passou a dizer isso.
🧪 Teste: poscalculo-mesmas-caixas — 23 checagens e 5 mutações, incluindo a
invariante que explica a tela inteira (a diferença entre orçado e real é, à vírgula, a máquina).
🧰 Só tela. Não precisa do Luan.
v2.37.815
📋 O histórico do pedido parou de ganhar uma linha a cada tecla. No pedido 23749,
em catorze segundos, apareceram oito “Chapa lançada”: 8 · zerada · 12 · 125 · 12 ·
1 · zerada · 8.000. Sete nunca aconteceram — é a digitação do número sendo gravada
pedaço por pedaço.
🔎 Por quê. O campo salva 600 ms depois de cada pausa — e isso é bom, o valor não
se perde. Só que a mesma passada escrevia no histórico. Quem digita pausando entre os
dígitos gera um evento por pausa. E pela REGRA ZERO histórico não se apaga: as sete
linhas ficam ali pra sempre, empurrando pra fora as que importam.
✅ Agora são dois relógios: o valor continua salvando rápido, e a linha do histórico
espera a digitação assentar. Fica uma linha, com o número em que a pessoa parou.
Mexer no campo e deixar o mesmo número não gera linha nenhuma; zerar continua sendo
registrado, porque zerar é um fato.
🪪 E o sensor voltou a dizer quem mexeu. As réguas e o liga/desliga do 🤖 eram gravados
com o autor vazio: as quatro telas liam um campo “nome” que o login nunca
preencheu. Agora perguntam pro mesmo lugar que o resto do sistema pergunta — então “foi você
que mudou a régua?” passa a ter resposta.
📡 A regra da v2.37.753 saiu do papel. Ela prometia que o pedido só aberto — o
caso do Arnaldo, que pega e vai direto pra máquina — entraria em produção sozinho ao passar
das caixas combinadas. Nunca disparou: o tablet nem buscava o sensor nesse estado.
Agora busca — mas só onde o 🤖 está ligado, pra nenhum tablet ficar batendo no
servidor de graça.
🧪 Testes: chapa-um-evento-por-lancamento (repete a digitação real do 23749,
com o relógio na mão) e sensor-autor-e-poll.
🔬 E a trava nova pegou um erro meu no mesmo dia: ao mexer na linha do sensor, eu quebrei
sem querer uma mutação de outro teste. O vigia da v2.37.813 acusou na hora. Ele também passou a
medir alvo ambíguo — quando o trecho que a mutação procura existe em mais de um lugar,
ela troca o primeiro e pode mexer na linha errada sem ninguém ver. Foi o que aconteceu
comigo.
v2.37.814
📄 Três consertos no papel: a gramatura da nota, a largura na tela e o rolo que sumiu na
máquina.
🔎 1 · A nota que entrou com “0 g”. O Estoque de Papel mostrava sete linhas do mesmo
papel, todas “0 g”, somando 32.906 kg. Era a NF da MAXXI: ela escreve a gramatura
como “100 g/m²”, e o sistema só sabia ler “120 GR”, a grafia do fornecedor antigo.
Sem casar, a gramatura virou zero — e como o nome do papel é o pedaço ANTES da gramatura,
a descrição inteira virou o nome, e cada largura virou um papel diferente.
⚠️ O que ia acontecer: o app da Qualidade exige gramatura ao receber o rolo. Quando
os 41 rolos dessa nota entrassem, o rolo ficaria com 100 e o livro com 0 — e o botão
“acertar” proporia lançar as 32,9 toneladas de novo.
✅ Agora o sistema lê as três grafias (g/m², GSM e GR)
— e nos três lugares que leem nota de papel: o PCP, o app da Qualidade e o servidor.
Consertar um e deixar dois pra trás é como nasceu a diferença que já existia entre eles.
🔎 2 · “0 mm” em toda linha. Desde 14/08 a tela do PCP imprimia zero na largura de
todas as 14 linhas: a consulta passou a devolver uma lista de larguras (uma linha de papel
pode ter bobinas de várias) e a tela continuou lendo um número só. Agora mostra
“1350 · 1370 mm”, e um traço onde não há rolo — que é a resposta honesta, não zero.
🔎 3 · O rolo que saiu e nunca voltou não tinha idade. O painel “Parados +60 dias” media
só o que está parado no galpão: o rolo que saiu pra máquina era contado e pulado.
Hoje são 24 rolos da JP (25.755 kg) há até 75 dias fora, e a tela dizia “0 parados”.
Agora o cartão “Na máquina” diz há quantos dias saiu o mais antigo e pra onde foi,
em âmbar quando passa de 30 dias — no papel impresso também.
🛡️ Sem prazo inventado: rolo na máquina não tem vencimento cadastrado em lugar nenhum,
então a tela mostra o número e a idade, não um limite que ninguém combinou.
❓ Continua em aberto, e de propósito: em “1200 MM X 1400 MM”, qual dos dois é a
largura. Só o XML da nota ou a etiqueta do rolo decide, e essa nota é anterior à guarda do
XML. Chutar seria pior que não saber.
🧰 Pro Luan: a leitura da nota no servidor mudou — precisa de pm2 restart.
As duas telas do navegador já valem sem isso.
🧪 Testes: tests/nf-papel-gramatura.test.mjs (roda os três leitores e exige que
concordem) e tests/rolo-parado-na-maquina.test.mjs.
v2.37.813
🔬 As travas do sistema voltaram a travar. O sistema se protege com testes, e cada
teste prova que presta estragando o código de propósito e exigindo que o defeito apareça.
Só que, quando a linha estragada muda de nome, o estrago deixa de acontecer — e o teste
passa a dizer “peguei” sem ter pegado nada. A partir daí aquela trava não trava mais, e
ninguém fica sabendo.
🔎 Quatro testes estavam assim, e um deles estava verde na lista: o do aviso de
romaneio incompleto garantia uma regra que tinha deixado de ser verificada. Os outros três
guardavam a conta do IPI, o papel de impressão e o romaneio por cliente.
✅ Agora existe um teste que vigia os outros. Ele confere os 554 estragos que a suíte
usa e reprova se algum deles não existir mais no código. Ele já se prova contra si mesmo, e mostra
quantos testes usam a forma segura (34) e quantos ainda não (59) — pra esse número
não crescer no escuro.
🧹 E a lista de falhas caiu de 10 para 1. Nove eram defeito de teste, não do sistema:
data congelada pela metade (o teste envelhecia sozinho e quebrava num dia qualquer), recorte que
não acompanhou função nova, busca por nome de arquivo que passou a achar o changelog em vez
da tag, e arquivo de configuração que mudou de pasta. Uma era do sistema: sobrou um nome de
autor chumbado no “corrigir quantidade”, que a regra da v2.37.448 proíbe.
📋 A que sobra espera a sua decisão: ela cobra um conserto que existe pronto e sem
commit numa pasta de trabalho — o aviso de renomeação de caixa do caso de 09/09.
⚠️ Nada do sistema mudou além daquela linha do autor. Todo o resto foi conserto de teste.
v2.37.812
🧾 O orçamento passou a ter um total só. O mesmo orçamento saía com dois
números, um centavo de diferença: o PDF e a tela de aprovação diziam
R$ 11,85, e o WhatsApp, o cartão do vendedor e o link do cliente
diziam R$ 11,84.
🔎 Por quê. Desde a v2.37.733 o papel fecha o IPI em centavos — arredonda o
subtotal, o IPI e a ferramenta separados e só então soma. As outras contas não faziam
isso. Medido em 580.200 combinações: 16,6% dos orçamentos com IPI 15% e
4,2% com 3,25% imprimiam números diferentes. Com IPI zero, nenhum — é o
arredondamento do IPI, e só ele.
🔢 Eram QUATRO contas, não três. A quarta — a do texto do WhatsApp — foi achada pelo
próprio teste de regressão, que confere se sobrou fórmula solta no código. Todas as
quatro agora saem da mesma régua.
🛡️ REGRA ZERO: orçamento já gravado fica com o número que foi enviado ao
cliente. Isto vale só pro que for salvo daqui pra frente.
🧰 Pro Luan: o link do cliente é servidor — precisa de pm2 restart pra
valer. Enquanto não reiniciar, o link continua com a conta antiga; as três telas do
navegador já estão certas.
🧪 Teste: tests/orcamento-total-um-so.test.mjs — 2,3 milhões de
combinações contra a régua real, mais a varredura que acusa fórmula solta (filtrando
comentários, §9.9). 4 mutações, todas acusadas.
v2.37.811
📡 O sensor parou de somar caixas de outro pedido. Este é o “contou a mais” que o dono
relatou. Quando o operador largava o pedido no fim do turno e alguém pegava de volta
depois, em dois segundos o campo “Caixas produzidas” vinha preenchido com tudo que a
máquina contou desde o zero antigo — incluindo o que ela rodou de outros pedidos no
meio.
🔎 A marca do sensor é um PAR: “o aparelho estava em tal número quando o operador já
tinha declarado tanto”. O fim de turno creditava o parcial e o zerava — quebrando o
par — mas deixava a marca no zero velho. Caso real: marca carimbada em 04/09, pedido
retomado em 09/09, e o campo veio com 24.064 caixas. Cinco dias de Slotter rodando
outra coisa.
🕳️ E a rede de proteção não pegava. O app só refaz a marca quando ela falta, quando o
aparelho reinicia (o número volta pra trás) ou quando a chave muda. Marca velha, com o
número só crescendo, passava reto.
✅ Agora a marca morre junto com o parcial. Ao creditar, ela é apagada, e em até 15
segundos o app carimba uma nova a partir do que o aparelho está marcando naquele
momento.
⚠️ MUDA O QUE O OPERADOR VÊ (decisão do dono, 12/09): depois de reabrir um pedido, o
contador mostra a tirada nova, começando do zero — não o acumulado da etapa inteira. O que
foi feito no turno anterior já virou registro e continua lá.
🛡️ O que NÃO mudou: se o parcial não chegou a ser creditado, a marca fica (o par
continua valendo); o turno encerrado, quem largou, o congelamento do tempo e o ritmo seguem
iguais.
🧪 Teste: tests/sensor-marca-morre-ao-largar.test.mjs — roda o código real do
largar, a régua real do app e o merge real do servidor, com 18 checagens e 4 mutações.
v2.37.810
💰 “Faturou” parou de contar dinheiro que não entrou. O Pós-cálculo escrevia
“Faturou R$ 11.137” no pedido 23749 — que é de 8.000 caixas e vale
R$ 7.864. Eram R$ 3.273 de receita que nunca existiu, num pedido só, e a
margem subia junto.
🔎 Por quê. A tela faturava pela quantidade produzida. Nesse pedido a Coladeira
foi lançada com 11.330 caixas — mais do que as 8.200 chapas que a Slotter cortou.
Não dá pra colar mais caixa do que se corta, e não dá pra faturar o que não foi pedido.
✅ Agora, sem nota lançada, fatura-se o MENOR entre o que o cliente pediu e o que a fábrica
fez. Cobre os dois casos normais: produção a mais não vira receita, e entrega
parcial fatura só o que saiu. Havendo nota, a nota manda — ela é o fato.
🛡️ O que NÃO mudou: o custo continua medido pela produção (é assim que se compara
custo por caixa entre pedidos de tamanhos diferentes), a quantidade produzida continua
aparecendo como produzida, e a margem prevista não se move — ela é preço menos custo
previsto dividido pelo preço, e a quantidade se cancela. Quem muda é a margem real, que
estava inflada.
🔢 E a conta continua aberta na tela: o parêntese ao lado do valor passa a mostrar a
mesma quantidade que foi usada, então dá pra conferir a multiplicação a olho.
🧪 Teste: tests/poscalculo-faturou-pela-nota.test.mjs — 16 checagens com os
números reais do 23749 e 4 mutações, todas acusadas.
v2.37.809
⏱️ A hora de máquina e a parada pararam de contar em dobro no Pós-cálculo. Eram dois
defeitos irmãos, do mesmo mecanismo: o registro é o retrato do lote, não da janela de
relógio — e dois lotes do mesmo trabalho descrevem o mesmo pedaço de tempo.
🔎 A hora. Quando o operador usa “imprimir prontos e continuar”, os dois registros
gravam o mesmo horário de início — e isso está certo, porque a máquina não parou. Errado
era o Pós-cálculo somar as duas janelas. Medido na carteira: 16 casos, 56 horas cobradas
a mais (a Coladeira do ASSADOS VERMELHO marcava 4,57 h para uma máquina que ficou 2,43 h).
🔎 A parada. Ao liberar o lote, a lista de paradas não era limpa — então o Finalizar
carregava de novo as que o parcial de turno já tinha gravado, com o horário de início
idêntico até o milésimo. No pedido 23749 (08/09) a tela dizia parada 8,02 h numa
Slotter cujas janelas somam 5 h 03.
✅ Agora a produção soma a UNIÃO das janelas (por máquina e por dia) e cada parada conta uma
vez. No 23749 a parada caiu de 481 para os 307 minutos que existiram de verdade.
🛡️ Os dois erram pro lado de contar A MAIS, nunca pro de esconder hora real: janela que
não encosta continua somando (2º turno é hora de verdade), o mesmo horário em dias
diferentes soma os dois, registro sem horário legível não inventa janela, parada sem
horário de início conta sempre, e o descarte é por máquina — duas máquinas paradas pelo
mesmo motivo contam cada uma.
🛡️ O que NÃO mudou: a quantidade (os dois registros continuam somando caixa), o
registro anulado (segue fora), o tempo de acerto e o dinheiro do papel.
🧪 Teste: tests/poscalculo-hora-e-parada-uma-vez.test.mjs — 20 checagens com o
caso real do 23749 e 5 mutações, todas acusadas.
v2.37.808
📊 O Pós-cálculo parou de acusar pedido que não tem nada de errado. A máquina de corte
aparecia com 0,00 h e o aviso “— não apontou nada”, e logo abaixo nascia outra
linha, com as mesmas horas, marcada “rodou fora do orçamento”. Em praticamente
todo pedido.
🔎 Era a mesma máquina com dois nomes. O orçamento chama de Slotter e Corte e
Vinco; o apontamento do operador chama de impressora e corte_vinco. O pedido que
tem orçamento gravado já traduzia os dois nomes desde a v2.37.612 — mas o caminho novo, que
projeta pelo cadastro da caixa (v2.37.788), nasceu sem a tradução. Como só 3 dos
253 pedidos com apontamento de corte têm orçamento gravado, o alarme saía na carteira
inteira.
⚠️ Por que isso é pior do que parece: aviso que toca em todo pedido ensina a ignorar o
aviso. No meio dos falsos havia um verdadeiro — um pedido que cortou 11.361 chapas
contra 10.000 lançadas — e ele passava batido.
✅ Agora a hora orçada e a hora apontada caem na MESMA linha, e quem rodou fora do orçamento
de verdade continua sendo acusado: a correção não trocou alarme falso por silêncio.
🛡️ O que NÃO mudou: o pedido com orçamento gravado (que já estava certo), as
horas, o custo-hora, o confronto da chapa e o dinheiro do papel — nenhuma
conta foi refeita, só o nome pelo qual as duas listas se encontram.
🧪 Teste: tests/poscalculo-casa-pela-chave-do-cadastro.test.mjs, que carrega o
de-para e o classificador de verdade dos dois lados — e deixa escrito por que o teste
anterior passava com o defeito no ar: ele usava só a Coladeira, que tem o mesmo nome
nas duas listas e por isso nunca denuncia nada.
v2.37.807
🔄 A carga transferida chega no app do motorista novo com a roupa DELE. Pergunta do dono (12/09/2026):
"se o caminhão mudou, a carga é transferida pro próximo motorista e já vai direto pro app de quem foi a
carga nova". Ir, ela já ia — a troca da v2.37.801 muda o dono da carga, e o app mostra as cargas de quem
está logado. Só que ela chegava vestida com a roupa do motorista anterior.
🛠️ O bloco vermelho de "caminhão quebrado" não é dele. Agora, quando existe uma troca depois da
quebra, o app mostra "🔄 Esta carga veio de outro caminhão" em âmbar, com de → para, hora e
motivo, e a linha que interessa: os pedidos que faltam estão aí embaixo, é só seguir a rota.
🚚 E o "Saí da fábrica ✓ 23:06" também não foi ele. A hora continua valendo — é da CARGA, e é
dela que sai a conta da entrega —, mas passa a ser dita como o que é: "a carga saiu da fábrica às 23:06,
na viagem anterior, antes de passar pro seu caminhão". Pôr na boca do motorista um toque que ele não deu
é o tipo de detalhe que faz ele parar de confiar na tela.
🚨 O conserto que mais importava: o caminhão novo também pode quebrar — e o botão estava
bloqueado pela quebra antiga, que continuava marcada na carga. Quem pegasse a carga e quebrasse na
estrada ficaria sem como avisar. Agora a quebra superada não barra a quebra nova, e ela volta a
aparecer vermelha, como tem que ser.
🔒 A quebra anterior não é apagada (REGRA ZERO): ela continua no percurso da viagem, com hora e
quanto tempo o caminhão ficou parado. Ela só deixa de ser o estado atual — a mesma régua que o card do
escritório já usa desde a v2.37.801.
✅ E quando o caminhão só conserta (mesmo motorista, mesmo caminhão), nada disso entra: o motorista
toca "↩️ Voltei a rodar" no bloco vermelho e segue a rota, como já era desde a v2.37.794.
🔧 Por dentro: trocaDaCarga + quebraSuperada, com
_motBlocoQuebra, marcarQuebraCarga e o botão da saída em
painel_motorista.html. 128 checagens · 16/16 mutações acusadas em
tests/percurso-da-entrega.test.mjs. Sem servidor e sem migration — nada pro Luan.
v2.37.806
🔎 Filtro por cliente e por período no 📉 Abaixo do preço. A tela mostrava a carteira
inteira de uma vez. Agora dá pra perguntar "e o ALPACK?" ou "e nos últimos 30 dias?"
sem ter que ler a lista toda.
📅 Período: 30 dias · 90 dias · este ano · tudo — pela data de criação do orçamento
(está escrito na barra). É a mesma régua do 📊 Conversão: duas definições de "últimos 30 dias"
acabariam discordando na mesma tela.
🤝 Cliente: a lista traz só quem tem orçamento salvo — não a carteira inteira. Um seletor
com 300 nomes, 290 deles sem orçamento nenhum, é lista pra rolar, não filtro. E ela acompanha o
período: cliente sem orçamento nos últimos 30 dias não aparece quando você escolhe 30 dias.
🔢 Os quatro números do alto saem filtrados junto. Isso é o principal: se só a lista fosse
recortada, o "deixado na mesa" continuaria falando do total e o filtro mentiria justo no número
que se lê primeiro.
🛡️ Três cuidados pra o filtro não esconder dinheiro sem você pedir: a tela abre sempre sem
filtro (o de ontem não fica guardado); escolher um período em que o cliente selecionado não tem
nada solta o cliente sozinho, em vez de travar numa tela vazia sem explicação; e quando o
recorte não acha nada, a mensagem diz "solte o filtro pra ver o resto" com um ✕ limpar
filtro do lado.
🛡️ Pra não repetir: o teste subiu pra 39 checagens e 15 mutações, todas acusadas
(tests/orcamentos-abaixo-do-preco.test.mjs) — inclusive "o filtro de período deixa de
recortar", "o resumo do alto NÃO sai filtrado", "o seletor volta a listar a carteira inteira" e "o
filtro fica guardado entre uma abertura e outra". Conferido no navegador: 3 itens → 2 (30 dias)
→ 1 (+ ALPACK), com o seletor mostrando só os 2 clientes que têm orçamento e zero erro de JS.
🔧 Por dentro: jpOrcVarrerAbaixoDoPreco(opts) passou a receber
{periodo, cliente} e recorta antes da varredura; jpOrcClientesComOrcamento
monta o seletor; o período sai do orcConvFiltrar/ORC_CONV_PERIODOS que já
existiam (js/46-orc-conversao.js). Sem servidor e sem migration — nada pro Luan.
v2.37.805
📦 O estoque da fábrica agora aparece em TODOS os apps — e é um só. Pedido do dono, na
sequência da v2.37.804: "deixa o estoque geral para todos o app ver e como se fosse um único para
todos", e "hoje o que vale é o da fábrica". É isso ao pé da letra: o número que aparece em
qualquer app é o do PCP, pela mesma conta que a tela da fábrica e o app da Expedição
usam desde ontem.
📱 Onde ficou o botão (📦 Ver estoque da fábrica): no app do operador
(no bloco ⚡ Ações), do encarregado, do motorista, da onduladeira (inclusive
quando a fila está vazia — é justo aí que dá vontade de olhar o que já está pronto), do
vendedor (junto de ➕ Orçamento e 📦 Lançar pedido) e do laudo. O app da
Expedição continua com a tela dele, que é a de operar a doca.
👁️ O que a tela mostra: paletes, caixas e clientes em cima; embaixo, agrupado por
cliente (o maior primeiro) com cada caixa, o pedido e "1 de 4 paletes" quando parte do lote
já embarcou. Tem busca por cliente, caixa ou pedido, e um 🔄 pra ler de novo. Abre na hora
com o que já foi lido e atualiza atrás.
🔒 Só consulta, de propósito. Não tem ✕, nem baixa, nem expedir: quem mexe no estoque
continua sendo o PCP e a doca (bipando o palete). Uma tela de consulta em 6 apps não
pode virar 6 portas novas de escrita num documento que já apanhou de "quem grava por último ganha"
(v2.37.562/572).
🛡️ E ela não inventa número. Sem servidor, sem o livro de saídas de paletes ou sem a
régua na tela, a tela diz isso em vez de mostrar um total. Estoque é número que manda
caminhão: número errado é pior que tela vazia. Palete que já foi no caminhão não conta —
era exatamente o defeito de ontem.
🛡️ Pra não repetir: 33 checagens · 5/5 mutações em
tests/estoque-geral-em-todo-app.test.mjs, contra o dado real de 12/09/2026:
confere que os 6 apps carregam a mesma régua e a mesma tela, que a soma dos grupos é o total
(nenhuma linha se perde no agrupamento), que o módulo não tem porta de escrita nenhuma e que
sem o livro de saídas o número inflaria (56 no lugar de 46).
🔧 Por dentro: js/82-estoque-geral.js (ler ·
linhasDoDoc · totais · porCliente · filtrar ·
abrir), que monta a tela como overlay no próprio body — assim ela não precisa
caber no sistema de telas de cada painel, e pôr num app novo é uma tag e um botão. A conta
continua no js/81-estoque-pa.js da v2.37.804: nenhum app recalcula nada.
Sem servidor e sem migration — nada pro Luan.
v2.37.804
📦 O estoque do galpão é UM — e as duas telas passaram a contar igual. O dono, com o
celular e o computador lado a lado: "no app da expedição tem CLIENTE TESTE, mas no estoque da
fábrica não tem". Era a mesma linha, do mesmo lugar, no mesmo segundo.
🔎 Conferido no servidor (12/09/2026): o app da Expedição mostrava 75 paletes ·
42.937 caixas, a tela da fábrica 32 paletes · 24.472 caixas — e no galpão havia
46 paletes · 32.872 caixas. Nenhuma das duas estava certa.
📋 Por que acontecia. O estoque é gravado como lista crua, e cada tela fazia as
suas contas em cima. A da fábrica descontava três coisas só na hora de desenhar (e nunca
gravava o resultado); o app não descontava nenhuma e ainda somava o lote inteiro —
contando de novo o palete que já embarcou. São 8.820 caixas e 19 paletes que
não existem, e isso não ficava na tela: é dessa lista que sai a lista de clientes da carga.
🔁 E o CLIENTE TESTE renasceu 10 vezes em 2 dias. Duas partes do sistema faziam
perguntas diferentes sobre a mesma caixa: a que coloca no estoque perguntava "sobrou
palete que ainda não saiu?" (sobrou: 24 paletes de 10/09) e a que tira perguntava outra
coisa e via uma carga de agosto — de um lote que está anulado desde 04/09. Uma punha, a
outra tirava, a cada vez que a tela era desenhada. Ficou tudo registrado no histórico:
10 entradas de 8.400 cx entre 10 e 12/09, por 4 usuários diferentes.
✅ Agora a conta é UMA, num arquivo só, e as duas telas chamam ela. Desconto do palete que
já saiu, linha repetida fora, e o que o PCP tira com o ✕ some também no celular do
expedidor. As duas telas mostram 46 paletes · 32.872 caixas, e o app passou a escrever
"1 de 4 paletes" igual à fábrica, em vez de mostrar os 4 como se estivessem lá.
🗑️ As linhas repetidas agora conseguem morrer. Havia 2 cópias (FK GRUPO 31644 e
EMPORIO PRIME fundo) que eram imortais: a fábrica as escondia na leitura, então o
🧹 Limpar duplicados respondia "nenhuma encontrada" com duas no servidor, e a
proteção do salvamento as devolvia a cada gravada. Ser cópia passou a ser explicação
suficiente pra sair — e a linha que fica é sempre a de maior quantidade (empate: mais paletes;
empate de novo: a mais antiga).
🔒 E o ✕ passou a grudar. A marca de "removida de propósito" era apagada um segundo
depois pelo próprio salvamento — no servidor havia 5 remoções registradas e zero
marcas de pé. Agora a marca viaja junto e sobrevive.
👀 O CLIENTE TESTE vai APARECER na fábrica — ele é estoque de verdade pelos próprios
livros do sistema (coladeira fechou 8.400 cx em 24 paletes em 10/09, e nenhum palete tem baixa).
Pra tirá-lo, o ✕ da linha: agora ele fica.
🛡️ O que NÃO mudou: pedido marcado Carregado ou Entregue continua saindo
do PA sem pergunta; entrada manual (a digitada na mão) ninguém encosta; e nada é
apagado — linha que este computador não sabe explicar continua de pé no servidor, como desde a
v2.37.562.
🛡️ Pra não repetir: 53 checagens · 9/9 mutações acusadas em
tests/estoque-pa-regua-unica.test.mjs, rodando contra o dado real de 12/09/2026
(as 9 linhas do estoque, o livro de saídas de paletes e as cargas) — começando pelo defeito da foto.
🔧 Por dentro: a régua nasceu no js/81-estoque-pa.js
(unir/semCopias/paletesVivos/sobrou/doDoc),
que o sistema.html e o painel_expedicao.html carregam. No app,
paRecalcular() é o único lugar que deriva o líquido, chamado pelos dois
snapshots (estoque e livro de saídas) e no boot. No js/03-estoque.js, a porta que remove
(removerExpedidasDoEstoque) passou a fazer a mesma pergunta da que adiciona
(§9.6, v2.37.555), com _estStatusDeSaida separando "o pedido diz que saiu" de "uma carga
levou"; os mapas porId/movPorId/chapasPorId viajam no blob pra o
PUT não apagá-los. Sem servidor e sem migration — nada pro Luan. (O conserto definitivo
desse último item é pôr o doc estoque no SO_MERGE da API, que aí sim
depende dele.)
v2.37.803
📉 Um botão pra ver quais orçamentos JÁ FEITOS estão abaixo do preço. A comparação da
v2.37.799 mora dentro do formulário do item — ela só aparece pra quem abre a caixa pra editar,
uma de cada vez. Pra saber a resposta de 300 orçamentos, alguém teria que abrir 300.
✅ Agora tem o 📉 Abaixo do preço, na barra dos Orçamentos, do lado do 📊 Conversão. Ele
recalcula cada caixa de cada orçamento salvo e devolve a lista do pior pro melhor, medida
em R$ do item inteiro — não em porcentagem. É de propósito: uma caixa 75% barata em 10 unidades
importa menos que uma 12% barata em 100.000.
🔢 No alto, quatro números: quantos itens estão abaixo, quanto isso soma em reais, quantos
estão no preço ou acima, e quantos não deram pra conferir. Um clique alterna entre "só quem está
abaixo" e a lista inteira.
⚠️ Ele avisa antes de você cobrar de alguém. A sugestão é recalculada com os cadastros de
HOJE — papel, custo-hora, margem. A pergunta que essa tela responde é "esse preço ainda
serve?", não "o preço estava errado quando foi feito". Está escrito lá em cima, em amarelo.
🔧 E marca os casos em que o próprio número é frouxo: item com máquina sem custo-hora no
roteiro faz a sugestão sair baixa — o item parece melhor do que é, e a diferença real é
maior que a mostrada; e o crédito de apara do Corte e Vinco, que o motor da sugestão não
conhece, aparece marcado na linha em vez de somar calado.
🕳️ O que não dá pra conferir fica à parte, não some. Chapa apagada do cadastro, item sem peso ou
sem preço gravado: vão pra uma lista embaixo, cada um dizendo o porquê. Se sumissem, o total
sairia redondo e falso. E um item que estoura no recálculo não derruba a varredura inteira.
⏱️ Roda só no clique, nunca ao abrir a lista de orçamentos: são todos os itens de todos os
orçamentos passando pelo motor de preço inteiro. Pendurar isso no render repetiria a lentidão do
tablet da v2.37.774–776. O modal pinta antes de varrer, senão a tela ficaria branca e
pareceria travada.
🛡️ Pra não repetir: 26 checagens em tests/orcamentos-abaixo-do-preco.test.mjs,
9 de 9 mutações acusadas — inclusive "item impossível de conferir passa a entrar como se estivesse
ok", "o ranking passa a ser pelo % e some o item de R$ 50.000" e "um item que estoura derruba a varredura
inteira". Conferido no navegador, clicando no botão de verdade, com orçamentos salvos de teste e
zero erro de JS.
🔧 Por dentro: jpOrcItemVsSugerido + jpOrcVarrerAbaixoDoPreco +
orcAbaixoRender em js/46-orc-conversao.js. A conta é a mesma do formulário —
orcCtxDoItem (js/08) montando o contexto e orcIntCalc (js/22) fechando o preço:
se a régua mudar, esta tela muda junto (§9.13). Sem servidor e sem migration — nada pro Luan.
v2.37.802
🔗 A "Entregas ao vivo" também passou a mostrar o nome do cadastro. A v2.37.795 juntou
"TRANS BERNAL" e "TRANSBERNAL" numa parada só no percurso e no app do motorista — mas o
card da Entregas ao vivo, que lista um pedido por linha, continuava mostrando as duas grafias
uma embaixo da outra. Quem olhava via dois clientes, e é um só
(CNPJ 33.765.650/0001-87).
✅ Agora as três linhas saem com TRANSBERNAL. O card continua com uma linha por pedido — é o
que deixa ver que um foi entregue e outro devolvido —, só o nome passou a vir do cadastro.
🔒 O palete não foi reescrito. É ele que casa com o romaneio e com o estoque; trocar a
grafia lá por causa de um rótulo na tela seria mexer em quem-é-quem por fora do cadastro. A grafia original
fica guardada do lado — nada se perde.
🎯 E como o conserto foi na régua compartilhada (evPedidosDaCarga), ele vale pro card
e pras paradas de uma vez — em vez de duas contas que um dia divergem.
🔧 Por dentro: evPedidosDaCarga (js/08) sobre o clienteNomeOficial do js/01.
123 checagens · 16/16 mutações acusadas em tests/percurso-da-entrega.test.mjs.
Sem servidor e sem migration — nada pro Luan.
v2.37.801
🔄 Passar uma carga pra outro caminhão — com o que aconteceu no histórico de cada pedido.
Pedido do dono (12/09/2026), depois do aviso de quebra da v2.37.794: o ATN-5I22 quebrou e a carga
teve que ir noutro caminhão, com outro motorista. "Tem que estar no histórico daquele pedido o que
aconteceu com a carga." A carga é a mesma — os paletes não se mexem; muda a placa e
quem dirige.
📍 Onde fica: no ✏️ Corrigir carga (o botão do Histórico de Cargas), em cima do tirar/pôr
palete — quando o caminhão quebra, é a primeira coisa que o PCP precisa fazer. Escolhe o caminhão, o
motorista e escreve o motivo. Se a carga está com quebra aberta, o bloco já vem vermelho e o
motivo já vem escrito: é digitar menos numa hora em que ninguém tem tempo.
📝 O que aconteceu vai pro histórico de CADA PEDIDO da carga, não só no rastro dela: quem abre o
pedido semanas depois e pergunta "por que essa entrega atrasou?" está olhando o pedido.
Fica lá: de qual placa pra qual, com qual motorista, o motivo e quem fez.
📄 O romaneio é CANCELADO. Ele congela a placa e o nome do motorista na emissão — deixar como estava
seria mandar o motorista novo rodar com um papel que diz outra placa e outro nome. O número
cancelado fica no histórico, riscado, com o porquê (REGRA ZERO: número nenhum é apagado ou reusado) e
você emite o novo pelo 📄 de sempre.
🚨 E o alarme para de mentir. Carga passada pra outro caminhão depois da quebra deixa de
aparecer como "🛠️ QUEBRADO" em vermelho: vira "🔄 CARGA PASSADA PRA OUTRO CAMINHÃO" em âmbar,
com de→para, hora, motivo e quem fez. Ela sai do topo da lista e do contador vermelho da aba — o caminhão
quebrou, mas a carga andou, e alarme que contradiz a linha de baixo dele deixa de ser lido.
⚠️ Avisa, nunca barra: motorista que ainda está na estrada em outra viagem aparece com o aviso e um
confirm — quem decide é o PCP, que sabe coisas que o sistema não sabe. E motivo é obrigatório: troca
sem porquê é mistério pro escritório resolver depois.
🔧 Por dentro: trocarCaminhao + trocaMaisRecente
(js/79-corrigir-carga.js, sobre o _salvarCarga/_rastro/
_cancelarRomaneiosDoCliente que já existiam) e evTrocaCaminhao no js/08.
119 checagens · 16/16 mutações acusadas em tests/percurso-da-entrega.test.mjs.
Sem servidor e sem migration — nada pro Luan.
v2.37.800
📏 A compensação por onda agora sai do SEU cadastro, não de um chute. A v2.37.797
fez a compensação seguir a onda — mas usando uma tabela escrita no código que ninguém nunca
conferiu. O dono perguntou a coisa certa: "está certo?". Fomos ver: lemos as 205 caixas
do cadastro e comparamos com a tabela, uma onda de cada vez.
✅ O que a tabela já acertava: na onda B, 2 · 2 · 2 · 2 · alt 6 é mesmo a
combinação mais usada (52 das 163 caixas preenchidas). Na BB, 4 · 6 · 6 · 4
está certo (25 de 35 no L1, 31 de 35 no C1).
🔧 O que estava errado — e foi corrigido: a altura da BB era 11 e a fábrica usa
12 (12 em 11 caixas, 11 em só 6). E o lap estava 30 na B e 45 na BB, quando a
fábrica inteira usa 35: 111 das 163 caixas B e 25 das 35 BB. O 45 da BB ainda era
maior que o 40 da BC, que é onda mais grossa — chute, e agora dava pra provar.
🔒 E o lap saiu da troca automática. Ele é 35 nas DUAS ondas — ou seja, não depende da
espessura do papelão: é da caixa, não da onda. Trocar a chapa e mexer no lap seria estragar um
número que não tinha nada a ver com a troca — o defeito da v797 ao contrário. Agora a troca mexe
nos 5 que seguem a onda, deixa o lap em paz, e a tela diz isso. O ↺ Desfazer
continua devolvendo os 6.
🤚 Onde NÃO se inventou número: E, C e BC continuam como estavam. O cadastro não tem
nenhuma caixa dessas ondas, então não há o que conferir — e número sem dado por trás é
chute com cara de verdade.
🔎 De quebra, a varredura achou 15 caixas ATIVAS hoje com a compensação de outra onda —
inclusive a da foto do dono (FRITOS · JESSE, onda B carregando 6·7·7·6 · alt 12,
que é de BB; a gêmea CX 25 · KININO é BB com os mesmos números, que é de onde eles vieram).
São 4 caixas B com altura de BB e 11 caixas BB com altura de B. O sistema
não mexe em nenhuma: a lista foi pro dono decidir uma a uma, porque compensação de caixa
é dele.
⚠️ Isto não virou regra automática — de propósito. A onda B tem 30 combinações
diferentes de compensação no cadastro e a BB tem 21: a compensação depende também do
modelo e do tamanho, não só da onda. Por isso a troca continua sendo sugestão com ↺ Desfazer,
e não lei.
🔧 Por dentro: COMP_ONDA_PADRAO (js/08-cadastros.js) conferida contra
GET /api/caixas; CX_COMP_IDS_ONDA (os 5 primeiros) é o que o
cxCompSeguirOnda reescreve. 45 checagens em
tests/compensacao-segue-a-onda.test.mjs. Sem servidor e sem migration — nada
pro Luan.
v2.37.799
📉 O que você cobra × o que o sistema sugere, lado a lado. Os dois números já estavam
na tela do orçamento a três centímetros um do outro — a sugestão na caixinha verde, o preço
no campo logo abaixo — e ninguém fazia a subtração de cabeça.
🔎 Foi o que apareceu na CX AGUA SANITARIA 4X5L. A sugestão do sistema era
R$ 4,636/un; o pedido saiu a R$ 2,694/un. São R$ 9.711 a menos naquele item
só — sem um aviso sequer na tela.
✅ Agora tem uma linha dentro da própria caixinha verde, colada no campo do preço:
⚠️ você está R$ 2,835/un ABAIXO do sugerido (−70,3%) — R$ 14.176,09 a menos neste item,
em vermelho. Cobrando acima, a mesma linha aparece em verde dizendo quanto a mais.
E quem clica em Usar este preço → vê só ✓ no preço sugerido.
🤝 Não é o aviso que já existia. O ⚠️ ABAIXO DO NOMINAL compara só o R$/kg do
papel contra o nominal da chapa. Setup, frete e margem — onde mora a maior parte da
diferença — ficavam de fora dele. São duas contas diferentes de propósito, e agora as duas
aparecem, uma embaixo da outra.
🛡️ O que ele NÃO faz (pra não virar aviso que ninguém lê): não acusa caixa pela metade
— enquanto faltar medida ou R$/kg, a linha nem nasce (comparar com zero daria "−100% abaixo" em toda
caixa nova, inclusive quando só o clichê está preenchido); e uma folga de 0,5% conta como
"no preço sugerido", pra centavo de arredondamento não virar alarme.
✂️ E o Corte e Vinco não vira acusado falso. O motor da sugestão não conhece o crédito
de apara, que o preço do item abate. Quando há apara, a linha diz isso — "a sugestão não
desconta o crédito de apara (R$ 0,420/cx) — essa parte da diferença é de régua, não de preço" — em vez
de fingir que os dois lados são a mesma coisa.
🛡️ Pra não repetir: 25 checagens em tests/preco-vs-sugerido-na-tela.test.mjs,
8 de 8 mutações acusadas, incluindo "abaixo e acima trocam de cor" e "o C&V vira acusado falso".
Conferido no navegador, no modal de verdade, nos quatro estados: sem preço, barato, no sugerido
(clicando no botão) e caro.
🔧 Por dentro: orcPrecoVsSugerido (js/08-cadastros.js) escrevendo no
#orc-int-vs, dentro do #orc-int-box. Compara
ORC_INT_ULTIMO.precoUn com o orcPrecoUnDoForm da v2.37.798 — a mesma
função que monta o item, então a linha fala do preço que vai pro cliente, não de uma terceira conta.
Roda no fim do orcRecalcItem, junto com a comissão e pelo mesmo motivo (o peso e o
R$/kg só ficam prontos ali). Sem servidor e sem migration — nada pro Luan.
v2.37.798
💼 A comissão parou de contar a mesma caixa duas vezes. No orçamento, era só clicar
no ✏️ de uma caixa que já estava na lista — sem mexer em nada — e o aviso do
vendedor aumentava sozinho.
🔎 O caso da foto, número por número. Uma caixa na lista: CX AGUA SANITARIA 4X5L,
5.000 un, R$ 13.468,86. Comissão de 3% = R$ 404,07. Ao abrir essa MESMA caixa pra
editar, a tela passou a dizer "neste item R$ 695,40" e "total R$ 1.099,47 sobre
R$ 36.648,98" — quase três vezes o que o vendedor ia ganhar de verdade.
🕵️ Eram DOIS defeitos no mesmo aviso. Primeiro, a caixa em edição continua na lista
(com o selo editando…) e o aviso somava ela de novo — a mesma caixa contada duas vezes.
Segundo, esse "de novo" nem era pelo preço que o dono está cobrando: vinha da sugestão do preço
inteligente (R$ 23.180,12 no lugar de R$ 13.468,86). Por isso nada batia com nada na tela.
✅ Editar não move mais o número. Abriu uma caixa da lista pra mexer, o aviso mostra o que
está salvo — R$ 404,07 — e fica parado ali, dizendo ✏️ editando um item da lista
(o valor só muda quando você salvar). Salvou, aí sim ele anda, já com o valor novo.
➕ Caixa NOVA continua somando ao vivo, que é como tem que ser: conforme você preenche
medida, quantidade e R$/kg, aparece nos itens da lista, nesta caixa nova e o
total dos dois. Enquanto faltar preço, ele não inventa comissão de item pela metade.
🧮 E o valor agora é o que você cobra. O aviso passou a usar a mesma conta que monta o
item quando você clica em adicionar — inclusive o clichê/faca diluído e o crédito de apara
do Corte e Vinco. Antes eram duas contas diferentes pro mesmo item; a do aviso era a que ninguém
estava cobrando.
🛡️ Pra não repetir: 22 checagens em
tests/comissao-nao-conta-duas-vezes.test.mjs, começando pelo defeito da foto
reproduzido com os números exatos do print. Conferido também no navegador: com o código
velho a tela devolveu R$ 1.099,47 sobre R$ 36.648,98, letra por letra igual à foto do
dono; com o conserto, R$ 404,07 sobre R$ 13.468,86.
🔧 Por dentro: orcPrecoUnDoForm (a conta do preço saiu de dentro do
orcAdicionarItem e virou régua única) + orcValorDoItemNoForm e
orcComissaoHint em js/08-cadastros.js. O aviso deixou de ler o
ORC_INT_ULTIMO e passou a fechar no fim do orcRecalcItem — antes ele
rodava no meio, com o peso do caractere anterior, e nem rodava quando faltava chapa ou
quantidade. Sem servidor e sem migration — nada pro Luan.
v2.37.797
📏 Trocou a onda, troca a compensação. No cadastro da caixa, mudar a chapa muda a
onda — e cada onda tem a sua compensação de aba, porque o papelão tem outra espessura.
Só que os seis campos da seção 4 · Compensações por aba não mudavam: ficavam com o número
da onda velha.
🔎 Era o caso da foto. Caixa marcada onda B carregando altura 12, que é da
BC (a da B é 6). Com a compensação errada sai errado tudo o que vem depois: a medida da
chapa, o peso, o valor, as medidas da impressora e as do riscador — e nada
disso acusa nada na tela.
✅ Agora a troca de chapa leva a compensação junto. Trocando de B pra C, por exemplo, os
seis campos viram o padrão da C na hora (3 · 3 · 3 · 3 · alt 8 · lap 35) e a chapa, o peso, o
valor e as duas réguas da máquina recalculam na mesma hora.
↺ E dá pra voltar atrás num clique. Aparece um aviso dentro do bloco dizendo de qual onda
pra qual foi a troca e mostrando os números que estavam lá — com um botão ↺ Desfazer do
lado, que devolve os seis de uma vez. Quem tem compensação ajustada na mão não perde nada: nada é
gravado enquanto não clicar em 💾 Salvar Caixa.
🛡️ O que NUNCA mexe sozinho: abrir uma caixa salva pra olhar (o que está gravado
manda, e só de abrir nada é reescrito); micro e papel cartão, cujo padrão é zero de propósito
(facão não dobra) — nunca zeram uma caixa preenchida; e o que você digitar na mão, que continua
mandando (e tira o aviso da tela, pra o ↺ não passar por cima).
🛡️ Pra não repetir: 34 checagens em tests/compensacao-segue-a-onda.test.mjs,
começando pelo defeito da foto reproduzido (onda B com a compensação da BC) e cobrindo o Desfazer,
a caixa nova, o micro e a abertura de caixa salva. Conferido também no navegador, no modal de
verdade: a tela reproduziu a foto do dono no botão (35 × 246 × 457 × 247 × 456 × 15) e
virou 35 × 243 × 453 × 243 × 453 × 15 ao trocar pra C.
🔧 Por dentro: cxCompSeguirOnda + cxCompDesfazer (js/08-cadastros.js),
chamados pelo cxChapaSelChange antes do aplicarPadraoOnda — que continua
só preenchendo campo vazio, como sempre fez. O carregamento do modal
(cxPopularChapasSelect) entra com a trava CX_COMP_CARREGANDO, senão o cadastro
se reescreveria sozinho só de ser aberto. Sem servidor e sem migration — nada pro Luan.
v2.37.796
💰 O "+ Novo Orçamento" voltou a abrir. O botão estava mudo: clicava e não
acontecia nada — sem aviso, sem erro na tela, sem nada. Não dava pra fazer orçamento novo
nenhum, e editar orçamento já salvo também não abria, porque é a mesma porta.
🔎 Não era o botão. O clique chegava certinho. O que morria era a montagem da tela,
uma linha antes de o modal aparecer: ela estourava calada, e a última linha — a que manda a janela
aparecer — nunca era alcançada. Por isso a impressão de botão quebrado.
🧹 Era um resto de faxina da v2.37.777. Naquela versão, o campo de caixa do Corte e
Vinco deixou de usar a lista do próprio navegador e passou a usar a nossa. A montagem da lista
antiga foi trocada, mas uma linha do jeito velho ficou pra trás — e essa linha, sozinha,
derrubava a abertura inteira.
⚠️ Pegava todo mundo, sempre. O estilo que o orçamento novo já abre marcado é
✂️ Corte e Vinco — justamente o único que faz essa lista ser montada. Não dependia de
cliente, de caixa cadastrada nem de máquina: com a lista vazia estourava igual. Está assim
desde 10/09.
✅ E a lista que a v777 queria entregar finalmente funciona: código repetido no mesmo
cliente aparece com o apelido pra desempatar (ex.: F0427 (tampa) e F0427 (fundo)), e
embaixo de cada um a medida por caixa, as poses e o custo da faca. Isso nunca chegou a rodar —
estourava antes.
🛡️ Pra não repetir. Essa função não tinha teste nenhum — foi por isso que a v777
subiu com o botão morto e ninguém viu. Agora tem: 24 checagens · 3/3 mutações acusadas em
tests/orcamento-novo-abre.test.mjs, incluindo o defeito real recolocado e a
lista vazia.
🔧 Por dentro: orcCvPopularSelect (js/08-cadastros.js) — o .map(…).join('')
virou .forEach(…) na v777, mas o .join('') do fim ficou; forEach
devolve undefined → Cannot read properties of undefined (reading 'join'), dentro do
orcRecalcItem() que roda antes do abrirModal('modal-orcamento').
Sem servidor e sem migration — nada pro Luan.
v2.37.795
🔗 Um espaço a mais parou de virar outro cliente. A carga ATN-5I22 de 10/09 saiu com 14
paletes da TRANSBERNAL — 9 grafados "TRANSBERNAL" e 5 "TRANS BERNAL". O percurso e o app do
motorista mostravam duas paradas pra um portão só, e o motorista descia duas vezes no mesmo
lugar.
🔎 No cadastro existe UM cliente (TRANSBERNAL, CNPJ 33.765.650/0001-87). A segunda grafia nunca foi um
cliente: foi um espaço digitado a mais. A régua da v2.37.730 — o nome que vale é o do cadastro — não
alcançava porque ela casa por nome exato, e a normalização junta espaços mas não os apaga.
✅ Conserto na FONTE. Agora, quando o casamento exato não acha, o espaço deixa de contar — e aí o
pedido novo digitado "TRANS BERNAL" já é gravado como "TRANSBERNAL". Como é o pedido gravado que vira
palete, romaneio, estoque e nota, isso conserta a coisa toda daqui pra frente, e não só a tela.
🚨 E ela erra pro lado seguro. O exato manda; a folga do espaço é só o segundo passo, e o candidato
continua tendo que ser ÚNICO: dois cadastros que caiam no mesmo nome sem espaço = não sei de quem
é, e ninguém se junta. Conferido nos 155 clientes do cadastro em 11/09/2026: nenhum par
difere só por espaço.
🔒 A régua de quem-é-quem não mudou. O normCliente — que o romaneio, o orçamento e as
caixas do cliente usam — ficou igual. Afrouxar ali mexeria em tudo de uma vez, calado. O que ficou
mais esperto foi só o resolvedor do nome do cadastro, cujo pior caso é reconhecer um cliente que antes
ele não reconhecia.
🗺️ E as paradas que já existem (percurso e app do motorista) passaram a agrupar pelo nome do
cadastro em vez da grafia do palete — então a carga de 10/09, que já está gravada errada, já aparece
como uma parada só, com as 25.643 cx somadas.
🔧 Por dentro: clienteNomeOficial + normClienteSemEspaco (js/01),
clientePorNome/clienteOficialMot no app do motorista e a chave do agrupamento no
js/80-percurso-entrega.js. 105 checagens · 16/16 mutações acusadas em
tests/percurso-da-entrega.test.mjs, com o caso real das duas grafias.
Sem servidor e sem migration — nada pro Luan.
v2.37.794
🛠️ Caminhão quebrado na estrada: o motorista avisa com um toque, e diz quanto tempo vai demorar.
Pedido do dono (11/09/2026), olhando a carga do REGINALDO que saiu 23:06 e não entregou nada:
"ele quebrou no meio do caminho, quero que tenha um aviso caminhão quebrado — o motorista coloca, e quanto
tempo demorar ele fica quebrado". Até aqui a tela mostrava "🚚 Saiu 23:06 · 0/3 · 🚗 A caminho",
que é o desenho de um caminhão rodando normal. Carga parada na beira da estrada e carga a caminho não
podem ter a mesma cara.
📱 No app do motorista, um botão 🛠️ Quebrei na estrada. Um toque já avisa o escritório —
o tempo e o motivo vêm depois. Quem está na beira da estrada às 2 da manhã não vai preencher formulário:
exigir texto é a melhor forma de não receber aviso nenhum.
🕐 O tempo em botões de um toque — 30 min · 1 h · 2 h · 4 h · o dia — e dá pra tocar de novo se
esticar. A previsão conta do toque em que ele a deu, não da hora da quebra: quem diz "mais 2 h" às 3
da manhã está falando de agora.
📍 E o lugar vai junto. O GPS do celular grava onde ele parou, e o escritório tem "🗺️ onde ele
parou" com link pro mapa — que é o que resolve o problema de verdade: mandar socorro. Com a margem do
aparelho (±) do lado, como em todo ponto do sistema.
🚨 No escritório, a "Entregas ao vivo" abre uma faixa vermelha no card: desde quando está
parado, há quanto tempo, o motivo, quem avisou e a previsão. O caminhão quebrado vai pro topo da
lista e o número da aba fica vermelho — o aviso precisa saltar de qualquer aba, e um número a
mais não salta.
⚠️ Previsão vencida vira "passou da previsão há X", NUNCA "consertado". A previsão é um palpite do
motorista; quem diz que o caminhão voltou a rodar é só ele. E o "↩️ Voltei a rodar" não apaga a
quebra: ela fica no percurso da viagem com a hora e o tempo que ficou parado (regra zero) — quebra que
some é quebra que não existe na conversa do dia seguinte.
🗺️ No percurso (clicando na linha do cliente), a quebra entra na linha do tempo entre o que
aconteceu antes e depois dela — é o que explica uma viagem que saiu às 23:06 e não entregou nada.
🔧 Por dentro: marcarQuebraCarga/quebraPrevisaoCarga/desfazerQuebraCarga
+ _motBlocoQuebra (painel_motorista.html, grava em porCarga por merge,
partindo do que já estava), evQuebra no js/08 e o passo da quebra no
js/80-percurso-entrega.js. 101 checagens · 14/14 mutações acusadas em
tests/percurso-da-entrega.test.mjs. Sem servidor e sem migration — nada pro Luan.
v2.37.793
⚙️ As réguas do sensor viraram uma tela — sem mexer no código.
Pedido do dono (11/09/2026): "uma tela de ajuste de sensor, configurável". No Mural, ao lado do
📺 Modo TV, apareceu o botão ⚙️ Sensor (só admin e PCP). Nele você ajusta as 5 réguas do automático:
• ajuste → produção: mais que N caixas nos últimos N segundos (e o buraco máximo entre contagens);
• contador parado por N segundos → pede o motivo;
• parada ou pausa aberta: mais que N caixas → retoma.
Cada campo mostra o padrão do sistema e o limite aceito; fora do limite não grava. O ajuste vai pro servidor
e o tablet recebe em até 15 segundos, sem recarregar — pelo mesmo caminho que já traz o 📡 e o 🤖 de cada
máquina. Na mesma tela, o fator peça→caixa de cada máquina e o estado dos botões 📡/🤖 (que continuam
sendo ligados no cartão da máquina, um lugar só). A pergunta ao ligar o 🤖 passa a dizer os números em vigor.
Sem nada gravado, valem os padrões de hoje (20 caixas em 2 min · 60 s · 5 caixas).
Só tela, sem servidor.
v2.37.792
💰 O dinheiro do papel entrou no confronto da chapa. A v2.37.789 mostrava quantas
chapas sobraram ou faltaram; agora mostra quanto isso custou.
✅ Três campos novos: papel projetado, papel usado (preço da
folha × as chapas que o corte apontou) e a diferença em R$, dizendo se gastou a
mais ou a menos.
🔑 O preço da folha sai do projeto — total do papel ÷ chapas
projetadas. Parece detalhe, mas foi onde eu errei primeiro: tentei calcular por caixa ×
poses, e isso ignora a quebra (uma chapa não rende poses caixas BOAS). O
preço saía inflado. O teste pegou, e a prova ficou guardada: usando exatamente as chapas
projetadas, o R$ real tem que bater no centavo com o projetado.
🚫 E ele fica vazio quando seria chute: sem a contagem de chapas do projeto —
o pedido que nasceu de orçamento antigo, que não guardava esse número — o
campo diz o motivo em vez de mostrar um valor quase certo. Papel é a maior parcela do
custo: um número errado ali faria o pedido parecer lucrativo.
v2.37.791
🔍 Achado ABRINDO O APP DO OPERADOR de verdade (o dono pediu pra conferir se ele já
lança certo). A conversão estava certa — mas o card mentia sobre o material.
🚨 No 24005 (20.000 cx, 2 poses, 10.560 chapas lançadas), o card escrevia em
VERMELHO: "📋 10.560 chapas −9.440 (47.2%)" — como se
faltasse quase metade do material. Ele comparava a CHAPA com o pedido em CAIXA sem multiplicar
pelas poses. A chapa dá 21.120 caixas: sobra 1.120. O operador lê isso
antes de começar — ou ele para no meio achando que o material não dá, ou
pede chapa que já tem.
✅ Agora o card diz "10.560 chapas × 2 = 21.120 cx +1.120", em verde.
O mesmo erro estava no bloco "📋 Chapas:" de dentro do pedido, que ainda escrevia
"cx" ao lado de um número que era chapa — virou
"10.560 chapas × 2 = 21.120 cx (suficientes)". Chapa curta continua acusando em vermelho,
e caixa sem pose tem a linha de sempre.
👀 Conferido na tela, com o app rodando: o campo de lançamento diz
"Chapas produzidas", e digitando 10.362 (o contador do Fabricio) aparece embaixo
"✂️ 10.362 chapas × 2 poses = 20.724 caixas". O que fica gravado é
20.724 — a conversão entra antes de salvar.
🧪 Teste: tests/operador-chapa-vira-caixa.test.mjs (26 checagens).
v2.37.790
📡 Máquina em pausa voltou a rodar → entra em produção sozinha com mais de 5 caixas (era 20).
Pedido do dono (11/09/2026): "quando a máquina entra em pausa e volta a produzir, ela entra em produção
sozinha — pode ser 5 chapas". Com o 🤖 O APP AGE SOZINHO ligado na máquina:
• parada do pedido (🛑, ou a pergunta de 60 segundos): passou de 5 caixas, retoma sozinha — antes eram 20;
• pausa livre (refeição, banheiro, troca de turno…): agora também. A pausa guarda o ponto do sensor
quando começa; passou de 5 caixas, o app encerra a pausa sozinho e avisa com o motivo dela.
Pausa aberta antes desta versão não tem o ponto do sensor e continua como
está até o operador encerrar. Sem sinal do aparelho, nada muda. O 20 de antes era medo do sensor contar
fantasma parado — medido depois, parado ele não conta.
v2.37.789
✂️ O confronto da CHAPA entrou no Pós-cálculo. Pedido do dono em
11/09/2026, fechando o raciocínio dele: "os dados acontecem depois dos apontamentos
— se usou folhas e tudo mais".
✅ Três números lado a lado, e cada um responde uma coisa:
PROJETAVA (quantas chapas o projeto pedia, já com a quebra) · LANÇADA
(quanto o PCP disponibilizou) · USADA (quanto passou na máquina de verdade,
pelo apontamento do corte). Mais a diferença em % e quanto sobrou do que foi
lançado.
🔑 A pegadinha que isso resolve: no Corte e Vinco o operador digita CHAPA, mas o
sistema guarda o registro em CAIXA (multiplica pelas poses). Pra voltar à chapa é
preciso dividir de novo — numa caixa de 2 poses, comparar direto erraria por
DOBRO.
🚫 E quando não dá pra saber, ele escreve isso em vez de mostrar zero: sem
apontamento no corte, ou sem as poses cadastradas, a coluna USADA diz
"não dá pra saber" com o motivo do lado. Zero ali significaria "a fábrica
não gastou chapa nenhuma", que é falso.
v2.37.788
📐 O Pós-cálculo deixou de mostrar um pedido só. Pergunta do dono em
11/09/2026: "hoje só tem ALPACK no pós-cálculo... e já fizemos
várias caixas!"
🔍 Por que era assim. Só entrava pedido que nasceu de um orçamento feito
aqui — é ele que guarda o previsto dentro do pedido. Os da fábrica vêm da
importação do Sectra ou são lançados na mão: nunca tiveram
orçamento, então não tinham com o que comparar.
💡 O raciocínio do dono resolveu: "o orçamento faz as caixas já
parametrando caixa, tempo de máquina, chapa, custo... a fábrica entra com o apontamento
pra ver se bate com o que foi projetado". Os parâmetros não moram no
orçamento — moram no CADASTRO DA CAIXA.
✅ Agora o pedido sem orçamento ganha o previsto PROJETADO na hora, com a
mesma máquina de conta que o orçamento usa: roteiro da caixa, velocidade,
custo-hora, e a cascata de quebra — que é de onde sai quantas chapas o pedido
precisava, o número que você pediu pra ver junto.
🔒 E ele vem CARIMBADO: a tela escreve "Projetado pelo CADASTRO da caixa, com os
preços de hoje". Isso responde "quanto esta caixa custa pra fazer, e o chão bateu
com isso?" — e não "errei o preço na época", que seria mentir com
cara de precisão. Quem nasceu de orçamento continua dizendo "Orçado na
v…", como antes.
🚫 E ele se cala quando não dá pra projetar: caixa sem cadastro, chapa não
encontrada, máquina sem custo-hora ou caixa sem a medida da chapa — o pedido fica de fora,
em vez de sair um número inventado.
v2.37.787
🏭 Na onduladeira, quem divide agora é a POSE — não o corte. Eram duas coisas
diferentes tratadas como uma só desde antes de a pose existir. Regra do dono (11/09/2026):
"chapa de 500 numa bobina de 1000 dá DOIS CORTES; na corte e vinco cada chapa vira duas caixas;
então se entrar mil caixas, tem que sair quinhentas chapas — o corte é determinado pela
largura da bobina".
📑 POSE = quantas caixas saem de 1 chapa (a faca) → é quem divide.
CORTE = quantas chapas saem lado a lado na largura da bobina → muda o
metro linear, nunca o número de chapas.
🚨 O que estava errado: a meta, o "Folhas" do card, o "Papel kg" e a
baixa de bobina saíam divididos pelo corte. Numa caixa sem pose com 2 cortes isso
era metade do certo (com 4 cortes, um quarto) — e o ✅ de "meta batida" mentia
junto, dando o pedido por pronto na metade. Nas caixas com pose só acertava por
coincidência, quando o número de cortes era igual ao de poses.
📏 E o metro linear media as CAIXAS em três lugares (a linha da lista, o detalhe
do pedido e o cálculo que sugere o rolo): numa caixa de 2 poses, pedia o dobro de bobina.
É o mesmo defeito que a v2.37.782 corrigiu na fila da Programação.
✅ O app da onduladeira não conhecia "pose" de jeito nenhum — agora conhece: ela
vem junto do pedido (desde a v2.37.780) e, quando não vem, sai do cadastro da caixa,
pela mesma régua do resto do sistema (só corte e vinco, só o número
cadastrado na mão). Cabeçote/Facão não muda nada: lá o pedido
já é em folhas.
🧪 Teste: tests/onduladeira-chapa-pela-pose.test.mjs (17 checagens, com o
exemplo do dono, e a conta antiga é acusada).
v2.37.786
📄 "📄 Romaneios emitidos" agora também no Histórico de Cargas. Pergunta do dono em
11/09/2026: "onde fica o histórico de romaneio?". Ficava num canto só — dentro do
bloco 📋 Histórico de cargas do 🗓️ Planejamento de Carga, que é uma tela de
planejar. Só que a pergunta "cadê o romaneio desta carga" nasce no
📜 Histórico Cargas da Expedição, olhando a carga que já saiu.
✅ Agora o botão está nas duas telas, no canto direito, em cima da tabela. Abre a mesma
lista: todos os romaneios do mais novo pro mais velho, cada um com 🖨️ Reimprimir (2ª via,
mesmo número e mesma data) e ❌ Cancelar (pede o motivo; o número não é reusado e fica
riscado com o motivo à vista).
🔧 Um botão, não dois. O markup saiu de dentro do Planejamento e virou
romBotaoHistorico no js/24, que é o dono do modal — as duas telas
chamam a mesma função. Dois botões escritos à mão viram dois comportamentos na primeira vez que
um deles mudar (§9.13, a régua da casa). 17 checagens · 7/7 mutações acusadas em
tests/botao-romaneios-emitidos.test.mjs — inclusive "escreveu o botão à mão de
novo" e "o container foi parar fora da tela". Só navegador — nada pro Luan.
v2.37.785
✏️ Agora dá pra corrigir a quantidade de UM lançamento — a linha que estiver
errada. No histórico do pedido, cada linha ganhou o botão ✏️ qtd.
O "Corrigir produção" que existia mira sempre o lançamento da última etapa
— e no 24005 (TRANSBERNAL · CX MORANGO) a errada era a primeira: Corte e Vinco
com 10.362 (o contador, que conta chapa) e Coladeira certinha com 20.450.
✂️ E ele já oferece a conta pronta: quando a linha é de corte num pedido
com pose, o painel mostra "essa caixa tem 2 poses — 10.362 × 2 = 20.724" com um
botão pra usar o número. Nada é gravado sozinho: o número cai no campo e
você confirma. Serve pra qualquer pedido de pose rodado antes da v2.37.780, quando o app do
operador passou a converter a chapa em caixa sozinho.
🔒 Corrigir não apaga (Regra Zero): o número de antes fica guardado e a linha passa
a mostrar "(era 10.362)", com o carimbo de quem corrigiu. A correção desce pro
banco, pro operador e pro quadro de concluídos — a mesma mecânica que o "Corrigir
produção" já usava, que agora é uma só pros dois caminhos.
⏸ E o aviso falso de MATERIAL PARADO morreu sozinho. Caixa não se cria na
coladeira: se ela fechou 20.450, o corte entregou pelo menos isso. O aviso passa a usar o
maior entre a primeira e a última etapa, então o 24005 — que já tinha ido
embora inteiro no caminhão — parou de acusar "9.638 cx no Corte e Vinco". Só
desliga alarme falso: o caso que criou o aviso (corte parado com chapa sobrando, fechamento
atrás) continua acusando igual.
✂️ E o "Esperado" da Programação parou de dividir duas vezes. Regra do dono:
"chapa de 500 numa bobina de 1000 dá DOIS CORTES; na corte e vinco cada chapa vira duas caixas;
então se entrar mil caixas, tem que sair quinhentas chapas". Pose (caixas por chapa) e
corte (quantas chapas cabem na largura da bobina) são coisas diferentes: quem divide é a
pose. O corte muda o metro linear, não o número de chapas. Dividir pelos dois pedia
menos chapa do que o pedido precisa.
🧪 Testes: corrigir-qtd-do-registro (17), operador-chapa-vira-caixa (19)
e programacao-fala-em-chapa (19).
v2.37.784
🧾 Romaneio novo sai com a carga inteira e CANCELA os anteriores — e dá pra reimprimir
qualquer um deles. Perguntas do dono em 10/09/2026, olhando o diálogo: "não entendi
onde está o romaneio 74 pra imprimir", "eu já gerei um novo, agora ele tem que sumir" e
"se eu gerar o 78 vai ser a mesma carga?".
🚨 Ia ser, e a conta estava feia. A carga do TRANSBERNAL tem 14 paletes e tinha
três romaneios valendo ao mesmo tempo: Nº 74 (5 pal), Nº 76 (9 pal) e Nº 77 (14 pal) —
28 paletes valendo pra uma carga de 14, a mesma mercadoria contada em dobro pro
faturamento. Emitir o 78 levaria a 42.
🗣️ E o aviso ajudava a errar: dizia "os antigos continuam no histórico", que se lê
como "deixam de valer". Eles continuavam valendo.
✅ Agora o botão fala a verdade e faz o serviço: "➕ Emitir romaneio NOVO — Nº 78 e
cancelar os anteriores (Nº 74, Nº 76)". Os antigos ficam riscados no histórico com o
motivo "substituído pelo romaneio Nº 78" — nada é apagado — e a conta da carga volta a
fechar. O aviso passou a mostrar quantos paletes cada papel levou e a soma, pra você ver o
dobro na hora.
🖨️ Um botão de 2ª via por romaneio. Antes só dava pra reimprimir o mais recente, e era por
isso que o Nº 74 não tinha caminho. Agora aparecem todos, com o nº de paletes de cada um.
🛡️ A ordem é o que protege a doca: cancela só depois que o novo gravou no servidor.
Se a emissão falhar, nada é cancelado — a carga nunca fica sem papel nenhum valendo com o
caminhão esperando.
💾 O PDF deixou de se chamar "Romaneio.pdf". Pedido do dono: "quero que saia o dia e o
número do romaneio, nome do cliente". Agora sai
"10-09-2026 - Romaneio 77 - TRANSBERNAL" — no sistema e no app da Expedição, pela mesma
conta. Sem acento e sem caractere que o computador recusa em nome de arquivo (era o
Nº e o · que faziam sobrar só "Romaneio").
🔧 Por dentro: romEscolherRomaneio devolve qual papel foi pedido,
abrirRomaneioCargaCliente encadeia o cancelamento, e nomeDoRomaneio
(js/54) batiza o arquivo e o título num lugar só (§9.13). 17 checagens · 9/9 mutações
acusadas em tests/romaneio-novo-cancela-anteriores.test.mjs. Só navegador
— nada pro Luan.
v2.37.783
🩹 A tela parou de congelar calada num documento que ela só lê. Print do dono (10/09/2026): na
"Entregas ao vivo", as cargas de 08/09 apareciam todas com "⏳ Ainda não saiu · 0/N entregues ·
🚗 A caminho". Não era a API. Conferido no servidor no mesmo dia: entregas_status tinha
4 registros de carga e 33 de pedido, com o pedidoId batendo palete a palete — a carga
FBW-4G22 tinha "saiu 11:35" gravado enquanto a tela dizia que ela não tinha saído.
O dado estava lá; o navegador é que não o carregava.
🕳️ O impasse. Esse documento é só leitura aqui desde a v2.37.736 (pra o sistema não apagar o que
o motorista grava). Com o carimbo de "até quando eu já sei" à frente do carimbo do servidor, o
carregamento caía no ramo "meu trabalho é mais novo, vou salvar" — e salvar num documento só-leitura não
faz nada. Nada aplicado, carimbo intacto. E o polling só pergunta de novo quando o servidor está à frente
do carimbo, então ele nem perguntava. Num documento normal isso se cura sozinho (o salvamento sobe e
volta com carimbo novo); num só-leitura não existia cura — travava até um motorista marcar algo novo,
sem nada na tela avisando que a informação estava velha.
🕰️ E como o carimbo ia parar no futuro: quando a resposta vinha sem a hora do servidor, ele era gravado
com o relógio deste computador. Num PC alguns segundos adiantado o carimbo nascia adiantado — e a
proteção que existe pra isso (v2.37.124) só reage acima de 1 minuto. Dentro dessa folga, travava.
✅ Três consertos, todos pequenos: documento só-leitura sempre aplica o que vem do servidor (não
há trabalho local pra proteger — quem escreve nele é o app do motorista, registro a registro); o carimbo
nunca mais é gravado com o relógio do PC (sem hora do servidor, não carimba: carimbo que falta faz
rebuscar, carimbo errado trava calado); e o polling passou a rebuscar quando o carimbo local está à
frente, que é estado impossível.
🔒 A trava que protege o trabalho continua de pé. Em documento normal, carimbo local à frente segue
significando "tenho coisa pra subir" e continua salvando, sem ser sobrescrito pelo servidor — é a
lição da v2.37.124 e ela tem teste próprio aqui.
🔁 Quem já está travado se cura sozinho: na próxima vez que a tela abrir (ou em até 8 s pelo polling),
o carimbo volta pro do servidor. Não precisa apagar nada.
🔧 Por dentro: aplicarRemotos, carregarDaApi e iniciarPolling do
setupSnapshotApi — e a mesma regra de carimbo no setupCadastroApi, que tinha a
mesma raiz. 13 checagens · 4/4 mutações acusadas em
tests/snapshot-so-leitura-travava.test.mjs (a camada de sincronização não tinha teste nenhum
até aqui). Sem servidor e sem migration — nada pro Luan.
v2.37.782
✂️ Na Programação, quando a caixa tem pose, o número agora é CHAPA —
não caixa. Pedido do dono em 10/09/2026, logo depois da v2.37.780:
"faz isso na programação também". A onduladeira produz chapa; o pedido do
cliente é em caixa. Com 2 poses, um pedido de 20.000 cx se programa com
10.000 chapas — e era a caixa que aparecia na tela.
📑 Onde mudou: o card da aba A programar, o card da Fila e o quadro do
modal de programar passam a mostrar "10.000 chapas · ✂️ 2 poses = 20.000 cx".
No modal ainda entra a conta escrita por extenso. Caixa sem pose não muda nada —
continua a linha de sempre.
🚨 E apareceu um erro de papel no caminho: o metro linear da FILA media as
caixas. A conta com poses existia em três lugares (a caixa das bobinas, o cálculo
do modal e o "Chapa produziu") e faltava no quarto — então, numa caixa de 2 poses, o
card do pedido, o total da bobina e o total geral da fila pediam o DOBRO de papel, com a mesma
tela mostrando um número na hora de programar e o dobro dele na fila.
✅ Agora a conta mora num lugar só (progChapasPed) e os quatro bebem dela
— quatro cópias da mesma conta é como a divergência nasce.
Teste: tests/programacao-fala-em-chapa.test.mjs (14 checagens, e o código de
antes é acusado).
❓ Uma dúvida ficou aberta pro dono (nada foi mexido): o "Esperado" do
Chapa produziu divide por poses e também por cortes. Se cortes é
quantas chapas saem lado a lado da bobina, essa segunda divisão sugere menos chapa do que sai
de verdade. É pergunta de fábrica, então a conta ficou como estava.
v2.37.781
🧾 O romaneio nº 74 voltou pro cartão da carga — e a 2ª via dele saiu com as medidas.
Achado pelo dono minutos depois da v2.37.779: "tinha 2 romaneios, agora só tem 1 — cadê o
outro com 5 paletes?". O papel nunca sumiu (nº 74, 5 paletes, 2.050 cx, valendo);
sumiu da tela. Isto foi defeito da v2.37.779, e é o conserto dela.
🧭 O que tinha acontecido. A v2.37.779 fez o lado da carga perguntar ao pedido de
quem é o palete — mas o lado do papel já emitido continuou comparando o nome
gravado. O nº 74 foi gravado como "TRANS BERNAL"; o cartão passou a procurar
"TRANSBERNAL" e não achava. Metade da pergunta com uma régua, metade com outra — e a
metade que envelhece é sempre a que já está escrita no papel.
🚨 E o risco não era só sumir da tela: carga que "não tem romaneio" queima número
novo — o motorista leva um papel e o faturamento recebe outro. É o defeito da v2.37.494
batendo na porta.
✅ Agora os dois lados usam a mesma régua. O papel gravado é reconhecido pelos
pedidos que ele mesmo carrega. O cartão da carga volta a mostrar os dois romaneios, a
conta de "já emitido" volta a contar o nº 74, e o cancelar/corrigir carga alcança o papel
de grafia velha.
📐 A 2ª via do nº 74 recupera medida, qualidade e peso: 485×294×240 mm · Onda BB ·
657g · 1.823 kg — conferido rodando a função real em cima do registro que está no servidor.
Sem mexer em número, data, paletes nem caixas: a 1ª via já está assinada.
🔒 Na dúvida, não troca a identidade do papel: se os pedidos dele apontarem para mais de
um cliente, ou se for papel antigo sem pedido gravado, vale o nome que está escrito nele.
🔧 Por dentro: clienteDoRomaneio + chaveDoRomaneio (js/54), usados por
js/24 (inclusive os três caminhos da 2ª via), js/58,
js/79 e o app da Expedição. 39 checagens · 14/14 mutações acusadas em
tests/romaneio-cliente-vem-do-pedido.test.mjs. Só navegador — nada pro Luan.
v2.37.780
✂️ No Corte e Vinco, a chapa que o operador digita volta a virar CAIXA.
Print do dono em 10/09/2026, pedido 24005 · TRANSBERNAL · CX MORANGO (20.000 cx):
no histórico, 10.362 na Máq. A Corte e Vinco (Fabricio) e 20.450 na Coladeira
(Mirailton) — quase o dobro na etapa seguinte. O operador digitou o que o contador da
máquina marcou, e o contador conta chapa: a caixa tem 2 poses, então passaram
20.724 caixas. O sistema gravou 10.362.
⏸ O sintoma na Carteira: o pedido, já carregado e com "saiu tudo (7 paletes)", ficou
acusando "MATERIAL PARADO · 9.638 cx no Corte e Vinco" — que é exatamente
20.000 − 10.362. O aviso da v2.37.767 estava certo; o número que ele leu é que não.
🔍 Por que a conta não rodou: ela existe desde a v2.37.147, mas o tablet não
tinha como saber das poses. A lista que o PCP publica pro operador mandava código, chapa,
velocidade, paletização… e não mandava a pose. Sobrava pro tablet
descobrir sozinho no cache de caixas — que pode estar vazio no aparelho recém-aberto
ou velho numa caixa cadastrada hoje. E tinha um agravante: essa resposta virava memória.
Perguntada uma vez no início, sem o cadastro na mão, ela respondia 1 — e esse 1
valia pelo resto do dia, mesmo depois das caixas chegarem.
✅ Agora são duas travas: a pose viaja junto do pedido (quem calcula é o PCP,
que tem o cadastro inteiro, pela mesma régua da Carteira — os dois passam a concordar por
construção); e, no tablet, quando o cadastro chega, a resposta velha é esquecida.
Quem respondeu sem saber pode mudar de ideia quando souber.
👁 O que o operador vê: no Corte e Vinco o campo continua sendo em CHAPAS, com a
conta ao vivo embaixo ("10.362 chapas × 2 poses = 20.724 caixas"). Slotter, Coladeira e
Grampeadeira não mudam nada, e C&V que paletiza (última da rota) continua
sem multiplicar — ali o palete já é contado em caixa.
⚠️ O registro de 10/09 do 24005 fica como está (Regra Zero — nem número
se muda): corrigir aquele apontamento é decisão do dono, pelo histórico do pedido.
v2.37.779
🚛 Um cliente, um romaneio — e de quem é o palete quem responde é o PEDIDO.
Foto do dono em 10/09/2026: o Romaneio nº 74, do TRANS BERNAL, saiu com
MEDIDA "—", QUALIDADE "—" e sem a coluna de PESO. E a MESMA carga tinha gerado DOIS
papéis do mesmo cliente, cada um com metade dos paletes.
🔍 O cadastro nunca esteve errado. Conferido no servidor antes de mexer: os pedidos dizem
TRANSBERNAL e apontam a caixa certa — 0 de 357 pedidos têm cliente fora do cadastro.
O nome torto mora só na cópia que o palete guardou na bipagem, feita em 27/08, antes de o
cadastro do cliente ser juntado. 646 paletes no histórico, 11 divergem — todos este mesmo
caso, em 2 cargas.
🧱 Por que o papel saiu mudo. A medida e o peso vêm da caixa, e a caixa é do
TRANSBERNAL; o papel estava em nome de TRANS BERNAL. Existe uma trava de propósito
ali: não imprime medida nem peso de um cliente no papel de outro — número errado no papel
ninguém questiona. Como os nomes não batiam, ela preferiu "—". Fez o certo com o dado errado.
✅ Agora o palete que tem pedido é do cliente do PEDIDO — nas quatro contas de uma vez:
quais clientes a carga tem, quais itens entram no papel, o que vai pro faturamento e qual é a
caixa. Resultado na carga de verdade: de 2 romaneios (um deles com "—" e 0 kg) para
1 romaneio com 485×294×240 mm · Onda BB · 657g e os 1.823 kg que faltavam.
Vale também pra 2ª via de um papel já emitido: ela recupera a medida que o registro velho
não tem, sem mudar número, data, paletes nem caixas — a 1ª via já está assinada.
🚫 E nome que não está no cadastro não passa mais calado (pedido do dono: "não deixa
puxar cliente que não está no cadastro"). Na hora de emitir, o sistema pergunta quando
um palete traz um nome que não existe no cadastro de clientes, dizendo quantos paletes e caixas
são. Avisa, nunca barra, e o palete nunca é tirado do papel — mercadoria saindo da
fábrica fora do romaneio seria muito pior que um nome torto.
🔒 A regra de ouro ficou mais forte, não mais fraca: o cruzamento passou a ser conferido
entre dois cadastros (pedido × caixa) em vez de contra um texto digitado no palete. Caixa
de outro cliente continua sem entrar por porta nenhuma.
🔧 Por dentro: clienteDoPalete + paletesForaDoCadastro
(js/54-romaneio-doc.js, o documento que o sistema e o app da Expedição dividem),
com js/24, js/58 e o app alinhados na mesma régua.
31 checagens · 10/10 mutações acusadas em
tests/romaneio-cliente-vem-do-pedido.test.mjs. Só navegador — sem servidor e
sem migration, nada pro Luan.
v2.37.778
🔍 As alterações numeradas do cliente saíam todas GRUDADAS numa linha só.
Pergunta do dono em 10/09/2026: "como que faz para ver o que o cliente digitou?" —
fui olhar onde o texto aparece e achei isto na v2.37.770, que eu tinha acabado de subir.
🚨 O pedido agora chega com uma linha por marcação ("1) … 2) …"), mas
dentro de um <div> comum o HTML come a quebra de linha: as duas alterações saíam
emendadas — justo o texto que precisa casar com o número desenhado na imagem.
Consertado nos 4 lugares que mostram esse texto: o detalhe da caixa e o card no
Desenvolvimento, e as duas linhas do próprio link do cliente (peça e amostra).
👁 Onde ler: 🧪 Desenvolvimento → abra a proposta → a caixa → no bloco
da arte aparece o cartão laranja "✏️ Fulano pediu:" com o texto,
a miniatura da marcação (clique pra ampliar e ver os números) e os anexos.
💬 E o cliente pode mexer em cada marcação, uma por uma — só que nada
na tela contava isso. Agora o aviso diz: "toque numa marcação pronta pra corrigir ou
apagar só ela", e o botão do diálogo virou "Apagar só esta" (o
🗑️ da barra é que apaga tudo). Comportamento que não se anuncia não existe.
v2.37.777
📦 Os campos de CAIXA do orçamento ganharam a mesma lista do cliente. Pedido do
dono depois de testar a v2.37.776 no iPad: "deu certo, faz isso com as caixas também".
✅ Referência / Nome e "puxar de uma caixa já cadastrada" (Corte e
Vinco) agora mostram os 8 mais parecidos com o código em cima e a
medida, poses e faca embaixo — e a busca acha tanto pelo código quanto pelo
nome da caixa, porque cada um lembra de um jeito.
🔧 E a mecânica virou UMA SÓ, dividida pelos três campos. Eram três
cópias esperando para desandar cada uma pro seu lado — agora o que fecha a lista, o que
corta em 8 e o jeito de escolher no dedo vivem num lugar só.
🔒 Um cuidado no campo do Corte e Vinco: quando o mesmo cliente tem dois
códigos iguais, o sistema desempata pondo o apelido do lado — e é esse rótulo
que vai pro campo, não o código cru. Sem isso, não dá pra saber qual das duas
caixas você quis.
🗑️ As listas nativas saíram inteiras — o elemento e a função
que as enchia. Fiação desligada esquecida no meio do código já deu problema
aqui antes.
v2.37.776
🍏 A lista de clientes do orçamento deixou de ser a do Safari. O dono testou no iPad
depois das v2.37.774/775 e continuou lento — e estava certo: o que sobrava não era conta
nossa, era o navegador. O campo usava a lista nativa, que no iPad engasga com carteira
grande.
✅ Agora a lista é nossa. Ela mostra os 8 mais parecidos enquanto você
digita, com o nome, a cidade/UF e a marca de inativo — e só essas 8 linhas
entram na tela, em vez de centenas. Tocar na linha preenche o campo e puxa o cadastro como sempre.
💡 Campo vazio também abre a lista, com os primeiros clientes — pra quando
você não lembra o nome exato.
🔒 Um detalhe que faz ela funcionar no dedo: a lista fecha por clique fora, nunca
ao sair do campo. No tablet, sair do campo acontece ANTES do toque na linha — e a lista
sumiria bem na hora de escolher.
ℹ️ Mesmos avisos de sempre embaixo do campo: cliente inativo, nome repetido em dois
cadastros e "não está no cadastro". Só a lista mudou de dono.
v2.37.775
⚡ A segunda metade da lentidão do tablet. A v2.37.774 tirou a
ordenação de cada tecla; faltava a limpeza de nome.
🔍 O que era. Pra comparar "deusa" com "DEUSA ALIMENTOS LTDA", o sistema tira acento,
pontuação e sufixos (ltda, me, epp…) de cada nome. Isso rodava três vezes
por cliente, a cada letra — numa carteira de 400, cerca de 1.200 limpezas por
letra.
✅ Agora o nome limpo é calculado uma vez e guardado junto com a lista. Medido no
teste com 400 clientes: 400 limpezas uma vez, e zero em cada tecla seguinte.
🔒 O que NÃO mudou, de propósito: a busca exata do cliente continua
varrendo o cadastro na ordem dele. Com dois cadastros de nome idêntico ela devolve o
primeiro da lista, e a lista guardada está ordenada — trocar ali poderia
amarrar o orçamento a outro cadastro, com o vendedor e a condição de
pagamento errados. Só a metade onde a ordem não muda nada foi acelerada.
ℹ️ Mesma sugestão, mesmos avisos (inativo, nome repetido, fora do cadastro).
Só ficou rápido.
v2.37.774
🐢 "Demora muito pra aparecer o cliente" no orçamento — pelo tablet. Queixa do
dono em 10/09/2026, usando o iPad.
🔍 O que era. A sugestão do cliente ordenava a lista inteira com
localeCompare em dois caminhos: a cada tecla digitada e a cada toque no
campo — e no toque ainda remontava centenas de opções no momento exato do
dedo. Ordenar por nome é das operações mais caras que existem em JavaScript; no
computador passava despercebido, no tablet trava.
✅ Agora ordena UMA vez e guarda. Medido no teste com 400 clientes: a primeira vez
faz 1.226 comparações — e cada tecla seguinte faz zero. Antes eram
1.226 por letra.
🛠 E ele continua percebendo o cadastro mudar: cliente novo entra na sugestão na
hora, e renomear também — porque salvar o cadastro de cliente derruba a lista
guardada de propósito. Sem isso, o orçamento sugeriria o nome velho.
ℹ️ Nada mudou na tela: mesma sugestão, mesma lista, mesmos avisos de cliente
inativo e de nome repetido. Só ficou rápido.
v2.37.773
📋 O operador passou a ver a ficha DELE, no aparelho dele. Pedido do dono em
10/09/2026: "quero que ele tenha a ficha pra poder visualizar o que ele fez e o que ele
está fazendo... ele iniciou, ele parou a máquina, por que que parou, quais são as
ocorrências, tudo registrado dentro de cada pedido".
🔍 O relatório já existia — e com quase tudo: pedidos concluídos,
caixas, peso, paletes, tempo produtivo, tempo parado, ajustes, perdas e as paradas com o
motivo (inclusive "Falta programação" e "Esperando chapa", que é o horário
perdido). Só que a única porta era o botão "Fim do turno" — e
ninguém abre um botão com esse nome no meio do expediente só pra dar uma olhada.
✅ Agora tem "📋 Minha ficha" no menu do operador, abrindo a mesma tela em modo
só olhar. E ela ganhou o que faltava: pedido a pedido, na ordem da hora — que
horas começou, que horas acabou, quanto fez, quanto de ajuste, por que parou e por quanto
tempo, e quanto perdeu, com o dono da perda do lado ("minha" / "veio da Corte e Vinco").
🚨 Abrir pela ficha ESCONDE o botão "Finalizar turno" que mora dentro dessa tela.
Deixar ele ali no meio do expediente seria convidar o toque errado — e fim de turno não se
desfaz.
⚙️ Sem consulta nova no banco: o servidor já lia hora, ajuste, paradas e perdas
de cada pedido pra somar — e jogava o detalhe fora. Agora ele devolve junto, na mesma
consulta. Precisa de restart da API.
v2.37.772
🧭 "De quem é essa perda?" — a pergunta agora tem número e dono. Pedido do
dono em 10/09/2026: "quando o operador manda a Slotter pra Coladeira uma quantidade de caixa, por
exemplo de mil caixas, e a Coladeira cola novecentos e oitenta, essas vinte caixas a Coladeira tem que
avisar pra onde está indo, se é a caixa dela ou se é a caixa duma etapa anterior".
✅ Na finalização, o app do operador já perguntava sobre perda — o que
faltava era ele saber o número. Agora, quando a etapa de fechamento termina com menos do que a
anterior entregou, a tela já abre dizendo "o Corte e Vinco entregou 1.000 e você fechou 980
— faltam 20", com o campo preenchido e dois botões: 🔧 Perda minha ou
⬅️ Veio assim do Corte e Vinco. O número continua editável: é
sugestão, não acusação.
📋 E fica registrado na Ficha do Operador, do lado da perda: "perda minha" ou
"veio da Corte e Vinco" — a conversa passa a ter endereço.
🧰 A conta já existia, só ninguém usava pra perguntar: pra uma etapa de
fechamento, a meta do operador já é "o que o corte liberou".
🚨 E ele CALA nos casos certos, que é o que impede virar clique automático:
fechou o número cheio → não pergunta; fechou bem menos (fora da folga de 10% da
chapa) → isso é falta produzir, não perda, e quem cuida é o aviso de
incompleto; no Corte não pergunta, porque o que sobra ali é chapa que ainda vai
rodar; e com o corte ainda rodando também não, porque a meta ainda vai crescer.
ℹ️ Perda antiga não ganha dono inventado — quem foi lançado antes
desta versão aparece como sempre apareceu.
v2.37.771
🚚 "CARREGADO PARCIAL" virou status de verdade. Pedido do dono em 10/09/2026:
"quero que o card tenha um carregamento parcial — pronto pra carregar, mas o carregamento é
carregado parcial; e deixa embaixo, como já existe, quantos paletes tem, quantos foram e quantos
ficou pra trás". Em agosto ele tinha escolhido só o selo, pra não mexer no
status; agora pediu os dois.
🔑 O que fez isso ser seguro: o parcial é irmão do "Pronto p/ carregar",
não do "Carregado". Medi antes de mexer: 84 lugares perguntam "é carregado?" e
46 perguntam "é pronto p/ carregar?". Quem pergunta a primeira quer dizer "já saiu
da fábrica, acabou" — e num parcial metade ainda está aqui. Tratar o parcial
como carregado o faria sumir do operador, do estoque e da cobrança. A varredura foi nos 46.
⚙️ Ele acontece sozinho: quando parte dos paletes embarca na carga bipada, o status sai
de "Pronto p/ carregar" e vira Carregado parcial, usando a mesma conta do selo — card e
selo nunca podem se contradizer. E quando o último palete sai, ele fecha em "Carregado":
status novo que não sabe sair seria pior que status nenhum.
📑 O selo continua igualzinho embaixo, com quantos paletes o lote tem, quantos foram e
quantos ficaram.
🚨 Esta versão precisa de restart da API. O servidor tem uma tabela própria que impede
status de voltar pra trás, e status que ele não conhece ele ignora, mantendo o
antigo. Sem essa linha, "Carregado parcial" seria recusado no sync e sumiria no F5. Entrou nas
duas tabelas, a do navegador e a do servidor.
🛠 Onde mais entrou: alertas da fábrica, romaneio (o que ficou ainda pode entrar num
romaneio novo), agendamento de entrega, laudo, app do vendedor, rodadas do pedido e a
importação — que nunca pareia data de pedido que já embarcou parte.
v2.37.770
📝 No link do cliente: apertar "Pedir alteração" na arte não fazia nada —
e agora dá pra desenhar um quadrado em cima do que está errado e escrever ali.
Os dois pedidos do dono em 10/09/2026, com a arte do KIMETAIS aberta no iPad.
🚨 O botão nunca esteve morto: a janela ABRIA, escondida atrás da arte. A tela
preta do visualizador e a caixa de "Pedir alteração" estavam no mesmo nível, e
empatadas ganha a que vem depois — que é a arte, com fundo preto. O mesmo apagava o
"Identifique-se" do botão Aprovar arte: eram dois botões mudos, e o cliente só
via nada acontecer.
⬜ Botão ⬜ Anotar, ao lado do ✏️ Marcar. O cliente dá zoom no
ponto (o endereço, o telefone, um código), arrasta um quadrado ou um círculo em
cima dele e, ao soltar o dedo, abre uma caixinha pra escrever o que muda ali. Cada
marcação ganha um número vermelho, desenhado na imagem que chega na JP, e o
texto dela viaja no pedido com o mesmo número — quem lê aqui acha o
2 no desenho e lê o que o cliente escreveu pro 2.
🔄 Dá pra tocar numa marcação já feita pra corrigir o texto ou apagar,
e o ↩︎ desfaz o último gesto, seja risco ou quadrado. Quem só marcou na arte
consegue enviar sem escrever nada no campo de baixo — a marcação já é o
pedido. Dois dedos continuam dando zoom, e o ✏️ Marcar à mão livre
continua igual.
⚠️ O texto não é escrito dentro da imagem de propósito: um endereço
inteiro por cima da arte fica ilegível e ainda tapa justamente o que ele está apontando.
v2.37.769
🔎 Desenvolvimento: a busca digitava de trás pra frente.
Ao digitar "sistemik" no campo de buscar cliente saía "siatemik": a cada letra a tela inteira era
redesenhada, o campo nascia de novo e o cursor voltava pro começo — a letra seguinte entrava na frente
das outras. Agora digitar redesenha só a lista de propostas; o campo fica quieto e o cursor onde você
deixou. Sem resultado, a tela diz que é o filtro, em vez de "nenhuma proposta ainda".
v2.37.768
⚡ Uma velocidade só: a do cadastro da caixa vale no Mural, no cronograma, no tablet e no pedido.
Pedido do dono (10/09/2026), olhando a FK GRUPO 31644: o cadastro da caixa dizia 618 cx/h na Slotter,
o Mural cobrava meta de 3.000 (o número digitado no pedido) e o modal do pedido sugeria
21.668 cx/h — eram quatro contas diferentes da mesma pergunta. Agora é uma só, nesta ordem:
1) a velocidade cadastrada na caixa para aquela máquina;
2) sem cadastro, a média real das produções medidas desta caixa — a mesma conta do bloco "Velocidades
por máquina" do cadastro, que deixa de fora lançamento manual e número impossível;
3) o padrão da máquina cadastrada;
4) por último, o número digitado no pedido.
Onde muda: o Mural passa a cobrar a meta certa (e o "abaixo da meta" fica honesto); o cronograma
deixa de pôr a média real na frente do cadastro; o tablet recebe a velocidade por máquina; e o
modal do pedido mostra de onde veio o número e já preenche o pedido novo com ele. O que você digitar no
pedido continua salvo e nunca é atropelado — só deixa de ser a primeira palavra.
O histórico de velocidade continua no cadastro da caixa (bloco 9), alimentado
sozinho pelas produções medidas. O botão "Usar" ali grava a média no cadastro quando você quiser.
v2.37.767
🔧 "Falta produzir 84 cx na Coladeira" — onde estavam essas 84 caixas? Em lugar nenhum.
Pergunta do dono em 10/09/2026 na linha do DEUSA 01.02.
🔍 O Corte lançou 5.692 e a Coladeira lançou 5.608. As 84 de
diferença são refugo — não existe pilha esperando cola, e mandar reabrir
a Coladeira era mandar procurar o que não existe. Pior: esse número pequeno
escondia o buraco de verdade.
✅ Agora o aviso mede contra a CHAPA LANÇADA, que é o teto de quem corta.
No 01.02: foram lançadas 8.000 cx de chapa e passaram 5.692 na máquina
→ a linha avisa "falta passar na máquina · 2.308 cx no Corte e Vinco". Isso é
material parado no chão, que é o que interessa. Regra do dono, textual: "o pedido
é de 10 mil, foi lançado 8 mil chapas e passou 5 na máquina — tem que avisar que
falta 3 mil pra passar".
🚨 E apareceu um buraco sério testando o exemplo dele: um pedido de 10.000 com
8.000 de chapa onde passaram 5.000 vira "Carregado" hoje — a trava do Carregado
compara o que o corte entregou com o que o fechamento fechou (5.000 e 5.000, batem) e
ninguém olha a chapa. O caminhão sai e 3.000 cx de material ficam no chão sem
ninguém ver. Agora o aviso continua de pé mesmo no pedido já carregado
(⏸ MATERIAL PARADO) — ele avisa, mas não prende o caminhão.
📉 O refugo saiu do card (decisão do dono). A Carteira fala do pedido — o que
falta passar e o que falta colar. Quem responde por refugo é o operador, e o lugar disso é a
Ficha do Operador.
🧭 A régua que separa refugo de pilha: a diferença entre o corte e o fechamento
só é refugo quando cabe em 2% E é menor que um palete daquela caixa
— a prova física: se não dá nem um palete, não há pilha pra
ninguém achar. Falhando qualquer uma, continua "falta colar", com o botão de reabrir.
🔒 E o aviso tem folga, senão gritaria todo dia: chapa se lança com sobra
(apara, defeito, acerto), então o corte quase nunca fecha o número exato. Só avisa
quando sobra mais que 10% da chapa (piso de 50 cx) — a mesma régua que o app do
operador já usa pra decidir que a chapa acabou. Os dois passam a concordar sempre: se o
sistema deu a chapa por fechada e reprogramou o resto, aqui não sobra material pra avisar.
ℹ️ O que não tem chapa continua como sempre: o sistema reprograma sozinho
quando a chapa fecha, desde a v2.37.729. Isto aqui não mexe nisso.
v2.37.766
🔒 A segunda porta que segurava o banco ganhou o mesmo relógio. Pedido do Luan em
10/09/2026, depois de ele pegar ao vivo no banco uma conexão parada com a transação
aberta segurando outras duas por 22 e 9 segundos.
🔍 O que era. A v2.37.761 já tinha consertado o salvar do PCP, que abria UMA
transação e falava milhares de vezes com o banco dentro dela. Conferindo a consulta que o Luan
capturou, apareceu que a mesma forma continuava numa segunda rota — a que recebe os
apontamentos do operador: abre a transação, faz de 3 a 4 perguntas ao banco por
registro e só fecha no fim, sem relógio nenhum.
⏱️ Agora ela desiste em 10 segundos, igual ao salvar do PCP. Se a trava não vier
nesse tempo, a requisição solta a vez em vez de ficar segurando uma das 10 conexões —
que é o que fazia a API inteira entrar em fila.
🛡️ Nada de apontamento se perde nisso, e foi conferido linha por linha antes: quando a
gravação falha, o registro continua guardado no tablet e ele tenta de novo a cada 60
segundos, sozinho; e o reenvio não duplica, porque a rota já recusa registro repetido
tanto pelo código dele quanto pelo conteúdo (mesmo pedido, etapa, dia, horário,
quantidade e operador).
🛠 Só servidor — nenhuma tela muda. Precisa do restart da API pra valer.
v2.37.765
⏸ Pedido que JÁ EMBARCOU e não deu baixa — a linha dizia duas coisas ao mesmo tempo.
Foto do dono em 10/09/2026: as 6 caixas do pedido 24063 · DEUSA ALIMENTOS saíram
no MESMO caminhão (romaneio nº 72 — 18 paletes, 16.661 cx), e a Carteira mostrava
"Esperando programação", "Em produção" e "Pronto p/ carregar"
bem do lado de "saiu tudo (N paletes)".
🔍 Eram TRÊS causas diferentes, e só uma era defeito.
01.07: a Coladeira lançou 2.128 cx e o romaneio levou 2.127 — a conferência
exigia bater caixa a caixa, sem folga nenhuma, então UMA caixa prendia o pedido para sempre.
01.51: a Coladeira nunca foi finalizada pelo operador — a trava está certa, o que
faltava era a tela dizer isso. 01.02: embarcou 5.608 das 8.000, ou seja há
2.392 cx cortadas paradas na fábrica — a trava também está certa; errada
estava a palavra na tela, que dizia "pronto p/ carregar" sem ter nada pronto pra carregar.
✅ O motivo agora fica NA LINHA do pedido (⏸ com o número: "FALTA PRODUZIR 2.392 cx
na Coladeira", "NÃO DEU BAIXA · Coladeira aberta · fulano"), em vez de morrer
num aviso de 1 segundo que só aparecia no computador onde a baixa foi tentada.
📋 Uma caixa no alto da Carteira junta todos os presos, cada um com o seu botão
(🔒 Liberar trava ou ✎ Abrir pedido), e o filtro novo
"⏸ Embarcou e não deu baixa" acha também os antigos — conserto que só
evita os novos deixaria os de trás presos para sempre.
🛠 E a baixa deixou de depender da lista de status: pedido que embarcou o pedido inteiro
vira Carregado mesmo estando em "Em produção" ou "Esperando programação" —
antes esses dois ficavam de fora da conferência e não tinham como sair de lá sozinhos.
🚨 O que NÃO mudou, de propósito: baixa manual no PA continua não
marcando "Carregado" (a regra de 13/08, quando uma limpeza de estoque marcou 7 pedidos sem caminhão
nenhum); entrega parcelada com palete ainda no PA continua esperando o resto e não ganha
aviso; e pedido que embarcou menos do que foi pedido continua fora de "Carregado" — ele só
passou a dizer quanto falta.
v2.37.764
📦 "Sem caixa no cadastro" numa caixa que ESTÁ cadastrada — a tela perguntava antes da lista chegar.
Foto do dono em 10/09/2026: o Estoque PA com ⚠️ sem caixa no cadastro em sete
linhas seguidas, e a Carteira com "Medida chapa —" nas mesmas caixas.
🔍 Conferido no servidor antes de mexer (205 caixas no cadastro): cinco daquelas sete o
sistema acha sozinho, sem vincular nada — DEUSA ALIMENTOS 01.01 e 02.01,
TRANSBERNAL CX FUNDO 10KG, NOGUEIRA 02 KING LEAO e Dcx PARMEGIANE P. Não
faltava cadastro: faltava a tela ficar sabendo.
⏱️ O que era. O cadastro de caixas tem 1,1 MB e vem do servidor depois do login.
A tela que foi desenhada antes disso foi desenhada com a lista vazia — e quando a lista
chegava, só duas telas eram avisadas: Cadastros → Caixas e Micro/Cartão. O
Estoque PA, a Carteira e o Plano de Carga ficavam com a resposta velha até alguém sair da aba e
voltar — que é exatamente o que fazia parecer que "consertava sozinho". E sem achar a caixa o PA
perde a paletização e passa a chutar os paletes: 2.127 caixas em 4 paletes, com o cadastro
dizendo 750 por palete.
✅ Agora, quando a lista chega, a tela aberta se redesenha — Estoque PA, Carteira (Relatório,
PCP, Entregas, Velocidades) e Plano de Carga, além das duas que já redesenhavam. Se você estiver
digitando num campo, ele espera você sair: redesenhar por cima apagaria o que estava sendo
escrito. É só desenho — não grava, não vincula pedido nenhum e não mexe em romaneio, etiqueta,
nota nem no que o tablet recebe.
🚨 As DUAS que continuam pedindo cadastro de verdade (essas o sistema não tem como adivinhar):
TRANSBERNAL TAMPA 10KG — o cadastro está "TAMPA 10 KG", com um espaço a mais que
o palete, e por isso os dois não casam; e EMPORIO PRIME, que não tem nenhuma caixa
cadastrada (0 de 205). A primeira sai no 🔗 da própria linha do PA ou acertando o nome no
cadastro; a segunda só cadastrando a caixa.
🧯 E não redesenha tela que não precisa. A de montar carga, por exemplo, volta pro
passo 1 e limpa a data quando é redesenhada — uma caixa salva no PC do lado apagaria a carga que
alguém está montando. A lista de telas é fechada de propósito.
🔧 Por dentro: jpRepintarTelaComCaixas (js/08-cadastros.js), chamado pelas
três portas que trocam o cadastro pelo que veio do servidor. 35 checagens · 8/8 mutações
acusadas em tests/caixas-chegam-repintam-a-tela.test.mjs. Só navegador — sem
servidor e sem migration, nada pro Luan.
v2.37.763
🕰️ Um computador com o relógio adiantado CONGELAVA o pedido no servidor — em silêncio. Queixa do dono (09-10/09/2026): "tinha chapa disponível, atualizou, sumiu as chapas", e antes disso "coloquei várias vezes hoje e ele saiu sozinho". A tela mostrava a chapa, a barrinha dizia "✓ Sincronizado", e no F5 a chapa não estava lá.
🔍 Como se descobriu onde NÃO era. O campo de status da Carteira não mostra o status gravado, mostra o calculado — e ele escreve "Esperando programação" pra todo pedido que está material disponível SEM chapa. Como a Importação do Relatório (a única coisa que grava esse status num pedido existente) não rodou naquele dia, o status nunca mudou: sumiu só a chapa. Isso descartou reprogramação, faxina de chapa e importação de uma vez.
🧨 A raiz. O carimbo que decide quem vence uma disputa (_chapaEditadaEm) é gravado com o relógio DO PC, em 18 lugares. As barreiras do servidor comparam esses números. Um PC com a hora adiantada grava um carimbo no futuro — e a partir dali toda edição feita de um computador com a hora certa tem carimbo menor e é recusada: a chapa não grava, o status não grava, o pedido inteiro não grava. E o servidor responde 200 OK, então a tela mente que sincronizou.
🩹 A casa já levou essa mordida uma vez — v2.37.117/118/124, o caso "no Mac atualiza na hora, no Windows demora". Lá o carimbo do polling nascia no futuro e travava a busca, e o conserto foi: "o servidor nunca pode estar atrás do próprio dado mais novo dele; se o local está à frente, o local está podre". Faltou aplicar a mesma lição no carimbo do pedido.
✅ Agora carimbo no futuro é lixo, e lixo não vence. Mais de 1 minuto à frente do relógio do servidor vale zero — a folga é a mesma de lá, absorve rede e arredondamento e só reage a relógio quebrado (horas, dias). Com o carimbo podre valendo zero, a edição de verdade volta a ganhar e o pedido descongela sozinho, sem ninguém mexer no banco. E o que chega é saneado: o carimbo do futuro é trocado pela hora do servidor, então a edição do PC com hora errada é aceita (ninguém fica sem gravar) e não envenena mais ninguém. O valor original fica guardado, pra dar pra rastrear qual computador foi.
📏 Régua única. As três barreiras (status, chapa e o bloco de dados) usavam cópias do mesmo SQL escritas à mão. Agora é uma função só — duas réguas pra mesma pergunta é exatamente como estes bugs nascem, e o teste trava isso.
🧰 Precisa do Luan: pm2 restart. Sem migration. ⏰ E confira o relógio dos computadores do PCP e dos tablets — a correção protege o sistema, mas o relógio errado continua errado (e atrapalha horário de apontamento, turno e relatório).
🔧 Por dentro: _carimboSql + _sanearCarimbo (api/src/routes/pedidos.js), no /sync e no /replace. Junto: a trava da lista do operador (v2.37.746) ganhou dedup por id, pra ela nunca ser a origem de um pedido repetido no tablet. 21 checagens · 6/6 mutações em tests/carimbo-no-futuro-congela-pedido.test.mjs.
v2.37.762
✂️ Pedido sem máquina gravada vai pro tablet da máquina do CADASTRO da caixa, não pra Slotter.
TRANSBERNAL · CX MORANGO (nº 24005, 10/09/2026): o pedido veio do relatório sem máquina, a caixa está
cadastrada na Corte e Vinco (2 poses) e a Carteira mostrava "✂️ Corte/Vinco · cadastro". Mas o que ia
pro tablet caía em "Máq. B Slotter": o pedido só aparecia na aba da Slotter, e o Fabricio o pegou lá —
apontamento, ritmo e sensor na máquina errada, com a Corte e Vinco rodando.
Agora o tablet recebe a mesma máquina e o mesmo roteiro que a Carteira mostra: o que o pedido tem gravado
manda; sem nada, vale o cadastro da caixa (pelo vínculo da caixa ou pelo código do mesmo cliente); sem
cadastro, o padrão de sempre. Vale também o processo do meio cadastrado na caixa.
O pedido do MORANGO já aberto na aba da Slotter: o Fabricio troca pra aba
Corte e Vinco e abre o pedido lá — o apontamento segue dele, só muda a máquina. Corrija a quantidade no campo
(o "1" veio do sensor da Slotter).
v2.37.761
🔒 "Falha ao sincronizar" no PCP: um salvar segurava a carteira INTEIRA travada até
terminar. Dois dias seguidos (09 e 10/09/2026) o salvar do PCP falhava em série, sempre com a
mesma cara. O Luan mediu no banco, com o problema acontecendo: 48 conexões de 1000 (não
era falta de conexão), dois pedidos parados esperando a vez (22 s e 9 s) e uma terceira
gravação com a transação ABERTA e parada, segurando as outras duas. A mesma consulta apareceu
presa duas vezes em poucos minutos: não era acaso, era um ponto do código.
🐢 O que estava acontecendo. A cada save, o PCP manda a carteira inteira pro servidor
(~400 pedidos). O servidor abria uma transação só e, dentro dela, falava com o banco
uma vez por pedido e mais duas por apontamento — milhares de idas e voltas com a
transação aberta. Enquanto ela não fecha, todo pedido que ela encostou fica travado: a
segunda aba do PCP, que só queria mudar UM pedido, ficava na fila atrás. E como o servidor atende
uma coisa de cada vez, no meio dessas idas ele ia servir outra tela (o carregamento do PCP é
um pacote de vários MB) — de transação aberta na mão. Era isso que o banco mostrava como
"parada sem fazer nada": o banco não estava lento; o servidor é que estava ocupado noutro lugar,
segurando a chave.
⚡ O conserto, em três partes. (1) O servidor passou a gravar de uma vez — um comando
pros pedidos e um pros apontamentos, em vez de um por um: milhares de idas viraram duas.
(2) A carteira é gravada em pedaços de 40 pedidos, cada um fechando sozinho — nenhum salvar
segura mais a carteira toda. (3) Os pedidos são gravados sempre na mesma ordem, então duas
telas salvando junto não se enroscam mais uma na outra. Se um pedaço falhar, os outros gravam
assim mesmo (um pedido com defeito não congela mais o PCP inteiro) e a barrinha continua
dizendo "falha ao sincronizar" — sem mentir que gravou.
🧯 Dois para-raios, pro dia em que outro caminho fizer parecido: quem espera uma trava
desiste em 10 s em vez de segurar uma das 10 conexões por 30 s, e transação aberta e
parada por mais de 60 s o banco derruba — soltando as travas sozinho. A importação de carteira
(/replace) continua sendo tudo ou nada, como tem que ser, mas também grava os
apontamentos de uma vez só.
🛡️ Nada mudou no que fica gravado. As 6 barreiras do salvar continuam palavra por
palavra (não rebaixa etapa, não zera chapa recém-lançada, não apaga baixa de faturamento, excluído
não ressuscita, apontamento não se apaga). A régua anti-duplicação de apontamento — a que
matou a multiplicação de 711 → 17 mil cópias na v2.31.49 — foi a parte mais delicada: no jeito
antigo cada apontamento enxergava o anterior, e num comando só isso não existe. O teste roda
o jeito novo e o jeito antigo lado a lado e exige que os dois terminem iguais, caso a caso.
🔧 Por dentro: inserirRegistrosEmLote/_dedupNoLote,
_sqlUpsertSync por jsonb_to_recordset e
gravarLoteDoSync (api/src/routes/pedidos.js);
idle_in_transaction_session_timeout (api/src/db.js).
37 checagens · 11/11 mutações acusadas em tests/pedidos-sync-lote.test.mjs.
🧰 É SERVIDOR: precisa do Luan — pm2 restart. Sem migration.
v2.37.760
🚨 Uma logo de cliente que faltava derrubava a publicação INTEIRA pro tablet da fábrica.
Foto do dono em 10/09/2026: "Erro ao publicar: Can't find variable: CLIENTES". Por trás
desse aviso técnico estava o estrago de verdade: a lista de trabalho não subiu, e o tablet do
operador ficou com a foto velha — sem ninguém saber, porque o único sinal era um toast que some
sozinho.
🔍 O que era. Na hora de montar o pedido pro operador, a publicação lê o cadastro de clientes
só pra pendurar a logo na etiqueta. Esse cadastro (CLIENTES) mora no
js/08-cadastros.js, que entra 22 arquivos depois daquele que publica. Quando o
js/08 não chega — aba carregada bem no meio de uma publicação de versão, cache pela metade —
o nome nem existe: não é vazio, é inexistente. A leitura estourava, o catch
abortava tudo e a lista da fábrica não ia.
✅ Agora a logo falta sozinha. Se o cadastro de clientes não estiver na página, o pedido sobe
sem a logo e a fábrica recebe a lista igual. Enfeite de etiqueta não pode barrar o trabalho
do turno. É a régua da casa de novo: avisa, nunca barra — e os vizinhos dessa mesma linha
(fpCaixaDoPedido, rotaDoPedido) já se protegiam assim; esta tinha ficado
pra trás desde a v2.24.0.
🔧 Por dentro: _publicarPedidosParaOperadorReal (js/02-firebase.js) — o
(CLIENTES||[]) defendia de valor nulo, não de a variável não existir; virou
typeof + Array.isArray. 16 checagens · 7/7 mutações acusadas em
tests/publicacao-operador-nao-apaga.test.mjs, com o caso rodando num sandbox onde o
js/08 realmente não carregou. Só navegador — sem servidor e sem migration, nada pro Luan.
v2.37.759
🕐 O horário do turno AVISA em tela cheia — e deixa o operador trabalhar. Pedido do dono
(10/09/2026): "o Arnaldo está rodando as máquinas e não consegue abrir o app por causa da
trava — reforça o aviso, mas deixa ele trabalhando". O app do operador fechava sozinho fora do
turno de propósito, pra ninguém deixar o app aberto com pedido preso. Só que junto com
isso havia uma parede no login: quem chegasse fora do horário do cadastro levava
"⛔ Fora do seu horário de acesso" e não entrava — fábrica parada por causa de um campo de
hora.
🚪 A parede virou porta com aviso. Fora do horário (e também "sem turno cadastrado", quando a
regra está ligada), o app abre um aviso em tela cheia: diz qual é o horário dele, que hora é
agora, que aquilo conta como HORA EXTRA, até que horas o app vai deixar ele trabalhar e
que não é pra deixar o app aberto depois de sair. Ele confirma —
"✅ VOU TRABALHAR AGORA" — e entra. A trava de APARELHO continua trava; só o horário
deixou de barrar.
👀 O PCP passa a ver quem entrou fora do horário, em 🔐 Acessos do operador: selo
"⚠️ entrou FORA do turno", um KPI "Fora do turno hoje" e um filtro só pra eles. Quem foi
avisado e desistiu também fica registrado.
📣 E o aviso ficou mais forte DENTRO do app, que é o que o dono pediu: a faixa do rodapé agora
aparece durante toda a hora extra — antes ela sumia enquanto faltasse mais de 30 min, então quem
entrava fora do turno passava 1h30 sem nada na tela dizendo que estava em hora extra. Ela
pisca quando falta pouco (≤15 min) e quando o horário já passou, e o app cutuca com bip e
vibração a cada 30 min: "o app fecha às 21:00 e vai cobrar a quantidade — não deixe o pedido
preso". Janela na cara, só no fim (30/15/5 min), como já era.
🕳️ O buraco que abrir a porta criaria foi fechado junto. Com o login liberado, quem entra
19:00 num turno que acabou 16:48 caía no relógio de fim de turno com o horário do
cadastro: dava −132 min e o app fechava o turno dele 20 segundos depois de entrar — o
mesmo laço da v2.37.425 (Arnaldo e Fabricio, 5 logins e 3 fechamentos em 90 s), agora pela porta
do cadastro. Agora ele ganha as 2 h de hora extra contadas do login, a mesma janela do
"SIM, vou continuar".
🌅 E quem chega CEDO não é hora extra. O Mirailton bate ponto 05:13 e a Coladeira abre
07:00: ele está "fora do turno" do mesmo jeito, e dar 2 h a ele fecharia o app às 07:13,
no começo do turno dele. A régua é o FIM do turno, não "está fora": fim ainda à frente = o
relógio é o turno dele; fim já passado = hora extra.
🔧 Por dentro: _avisoEntrarForaDoTurno e _dentroDoTurnoEm (a conta "estou no
turno?" agora aceita âncora — no login é "agora", no relógio é a hora do login, §9.8),
_turnoDoOperadorAtual caindo no _turnoHoraExtra, faixa com
piscar e _lembreteHoraExtra (painel_operador.html); rótulos
entrou_fora_do_turno/desistiu_*, KPI e filtro em js/01-core.js +
sistema.html. 55 checagens · 4/4 mutações acusadas em
tests/turno-avisa-nao-tranca.test.mjs. Só navegador — sem servidor e sem migration,
nada pro Luan.
v2.37.758
🛣️ "📍 Calcular pela rota" respondia "não achei o endereço da fábrica" — com o endereço da fábrica
cadastrado. Foto do dono em 10/09/2026: no cadastro do cliente, o botão da distância avisava
"⚠ não achei o endereço da fábrica (🏢 Dados da Empresa)". Só que 🏢 Dados da Empresa estava
preenchido — Rua Aparecido Durvalino Simpioni, 900, Jardim Paraíso · Boracéia/SP · 17270-000.
O aviso mandava conferir justamente o que já estava certo.
🔍 O que era. O endereço da fábrica fica guardado no servidor e só era trazido pra memória do
navegador por quem passasse em 🏢 Dados da Empresa ou em 🧾 Compras. Quem abria Clientes
direto — que é o caminho normal de quem vai cadastrar cliente — calculava a rota contra um endereço
em branco, e o cálculo respondia a única coisa que podia: não achei. Nunca foi o cadastro, nem
o mapa, nem a internet. Por isso funcionava pra quem tinha aberto Dados da Empresa antes na mesma
sessão, e falhava pra todo mundo que não tinha — o que fazia o defeito parecer aleatório.
✅ Agora a tela vai buscar o endereço da fábrica na hora de calcular, uma vez por sessão. O
km sai pela estrada, com o tempo de carro e a fonte, como sempre foi a intenção da v2.37.641.
Conferido com o mapa de verdade em 10/09: a fábrica é achada no número 900 e o FK GRUPO (Bariri)
dá 19,2 km · 24 min.
🗣️ E o aviso passou a separar dois problemas diferentes. Fábrica com o cadastro em branco não
é "não achei no mapa": é cadastro em branco, e agora a frase diz o que fazer —
"a fábrica está sem endereço — preencha cidade/UF (ou o CEP) em Cadastros → 🏢 Dados da Empresa" —
em vez de mandar procurar defeito no endereço do cliente. Nesse caso nem sai pra rede.
🚫 Nada mudou no resto da régua: km digitado à mão continua sendo a resposta da pessoa (o
preenchimento automático não sobrescreve, só o botão), e quando nada resolve o campo continua vazio —
km inventado é pior que km nenhum. Sem rede pro cadastro da empresa, a tela avisa e não quebra.
🔧 Por dentro: cliCalcularKmRota passou a chamar carregarDadosEmpresa() antes de
montar o endereço da fábrica (js/08-cadastros.js) — o _empresaCarregada segura o pedido em um
só por sessão. 21 checagens · 10/10 mutações acusadas em tests/km-pela-rota.test.mjs.
⚠️ O teste estava verde com o defeito no ar: o harness entregava o endereço da fábrica pronto pra
função. O caso novo monta a tela como ela é — a declaração vazia de verdade, tirada do próprio
arquivo. Só navegador — sem servidor e sem migration, nada pro Luan.
v2.37.757
🏢 O aviso de "CNPJ já cadastrado" é da hora de CADASTRAR — não de dentro do cadastro do cliente.
Foto do dono (10/09/2026): ele abriu o FK GRUPO só pra mexer no cadastro e levou um aviso vermelho
embaixo do CNPJ — "já cadastrado em FRISOKAR". Só que esse par já existia antes dele abrir a
tela: o aviso cobrava dele um problema que não era dele, numa tela onde não há nada a fazer sobre
isso. É a régua da casa de novo: aviso que não pede ação não aparece.
🔒 E era pior que barulho: o cadastro estava PRESO. A trava da v2.37.637 barrava o salvar em
qualquer cadastro com CNPJ repetido — então o FK GRUPO não gravava mais nada, nem uma correção de
endereço, nem a carta de isenção. O changelog daquela versão prometia "editar um cadastro que já tem o
CNPJ repetido continua funcionando"; o código fazia o contrário. Agora funciona como estava escrito.
🚧 A trava continua inteira onde ela existe pra valer. Cliente novo com CNPJ de outro:
avisa, diz quem já tem e não grava. E editando, se você trocar o CNPJ pelo de outro
cliente, barra igual — porque aí o repetido está nascendo agora. O que separa uma coisa da outra é
o CNPJ com que o cadastro abriu: mexeu nele, é problema novo; deixou como estava, é história
velha.
🔗 Nada foi apagado nem juntado (REGRA ZERO). Os pares repetidos continuam como estão — quem funde
dois cadastros da mesma empresa é o 🔗 Juntar repetidos, na tela de Clientes, quando o dono
decidir.
🔧 Por dentro: CLI_CNPJ_ORIG + _cliCnpjRepetidoNovo() no
js/08-cadastros.js — usados pelo aviso ao vivo, pelo 🔍 Buscar da Receita e pelo
salvarClienteModal. 15 checagens · 9/9 mutações acusadas em
tests/cliente-cnpj-repetido.test.mjs. Sem servidor e sem migration — nada pro Luan.
v2.37.756
📍 Onde o motorista estava quando tocou — e se aquilo é mesmo o endereço do cliente. Pedido do dono
(09/09/2026): "tem como colocar a localização quando o motorista clicar cheguei?". O app grava o ponto
do celular no 📍 Cheguei e no ✅ Entreguei, e o percurso passa a responder a pergunta que
interessa: ele chegou no lugar certo?
🗺️ No percurso, cada um desses dois passos ganha 🗺️ ver no mapa e a distância até o endereço
cadastrado do cliente: "✅ bate com o endereço cadastrado (a 34 m)" ou
"⚠️ a 9,2 km do endereço cadastrado". Quem geocodifica é o mesmo módulo do km pela rota
(v2.37.641), então não entrou serviço novo nem chave de API nenhuma.
🚫 E ela NÃO acusa no escuro. A conta só sai quando o cadastro do cliente resolve no número ou
na rua. Quando ele só chega no centro do CEP ou da cidade — que é boa parte do cadastro que veio do
Sectra —, a tela diz que não dá pra conferir em vez de estampar "a 4 km": cadastro ruim não pode
virar suspeita sobre quem está na estrada. Cliente sem endereço e cliente que não está no cadastro
também são ditos com todas as letras.
📏 A margem do GPS anda sempre junto (±12 m, ±300 m…). A céu aberto o aparelho erra
poucos metros; dentro de um barracão erra centenas. Ponto sem a margem é chute vestido de prova — e a folga
da comparação leva essa margem dentro dela, pra um ponto de ±300 m não "não bater" por 250 m de
diferença. Rua sem número ganha folga a mais.
⏱️ O toque nunca espera o satélite. A chegada e a entrega gravam na hora, como sempre; o ponto
vai depois, numa gravação separada e minúscula. Se o motorista negar a permissão, se o aparelho não
tiver GPS ou se demorar, não acontece nada — sem erro, sem aviso, sem toque perdido. É a régua da
casa: avisa, nunca barra.
🔒 Só no toque, nunca rastreamento. O celular não fica mandando posição: ele responde uma vez, quando
o motorista aperta o botão. Desmarcar a chegada não pede GPS nenhum.
🔧 Por dentro: _motPosicao + _motAnexarPosicao (painel_motorista.html, grava só os
campos do lugar por merge), _ponto/distanciaM/_conferir no
js/80-percurso-entrega.js, sobre o JPKmRota.geocodificar do js/95.
80 checagens · 11/11 mutações acusadas em tests/percurso-da-entrega.test.mjs.
Sem servidor e sem migration — nada pro Luan.
v2.37.755
🥇 Quando há trabalho seu preso, é ele que aparece na barrinha — mais nada. Foto do dono às 00:33 de 10/09/2026: a barra dizia "⚠ SERVIDOR FORA DO AR", mas ao clicar a janela dizia "ao salvar". Ou seja, o aviso que importava — existe uma alteração sua que não subiu — tinha sido apagado. O sistema busca novidades de 5 em 5 segundos e reescrevia a barra por cima do aviso do salvamento; e no segundo em que o servidor respondia, escrevia "● API conectada" em verde com o trabalho do dono ainda preso na tela. A tela mentia no pior momento possível.
🔒 Agora tem fila de prioridade: enquanto existe alteração esperando pra subir, só o salvamento escreve ali. Assim que ela sobe, a barra volta a mostrar o estado da conexão como sempre fez. Nada foi tirado — só deixou de atropelar.
🔁 E a janela do clique passou a dizer que o sistema está tentando sozinho. A v2.37.752 pôs essa informação no balão que aparece com o mouse por cima — mas o dono clicou, leu a janela inteira e ela não falava nada disso. Continuava parecendo que o trabalho estava parado esperando ele fazer alguma coisa, que é exatamente o que a 752 veio acabar. Agora tem uma faixa verde: "o sistema está tentando sozinho (tentativa N) — deixe esta aba aberta". O botão 📋 Copiar leva essa linha junto.
🔧 Por dentro: jpSaveEsperandoSubir() e o 4º parâmetro doSave do atualizarStatusSinc (js/02-firebase.js) — com try/catch no acesso às variáveis do retry, porque barrinha em branco seria pior que barrinha disputada. 44 checagens + 8 mutações em tests/aviso-sinc-clicavel.test.mjs. Só navegador — nada pro Luan.
v2.37.754
🏁 O motorista agora avisa que voltou pra fábrica — e a viagem fecha. Pedido do dono (09/09/2026),
logo depois do percurso da v2.37.751: aquela tela mostrava "🏁 Voltou pra fábrica —" sempre em branco.
Não era defeito: o botão nunca tinha sido feito pra CARGA. Ele existia só na viagem da escala
(desde a v2.37.392) — e a escala praticamente não é usada.
🕳️ O que esse buraco causava. Como ninguém escrevia a volta, o escritório contava o caminhão
na rua PRA SEMPRE: o número da aba "Entregas ao vivo" só sabia somar, nunca tirar. O card da carga
tinha o selo "🏁 Chegou" pronto e ele nunca acendia. E o percurso não tinha como dizer quanto tempo
durou a viagem inteira.
📱 No app do motorista, o botão 🏁 Cheguei na fábrica aparece depois do "🚚 Saí da
fábrica" (sem saída não há volta pra avisar) e fica em dois lugares: na aba 🚚 Entregar e no
card da aba ✅ Entregues. Precisa dos dois porque a carga sai da aba Entregar assim que o
último pedido é confirmado — bem na hora em que ele está voltando. Botão escondido numa aba de
histórico morreria sem uso, que foi o destino do da escala.
✅ Carga toda entregue, mas sem a volta, continua aparecendo — enxuta: "Tudo entregue. Falta só
avisar que você voltou" e o botão. O número da aba conta essa carga também, porque ainda tem um
toque a dar — e o número e a lista usam a mesma régua, senão o badge mente. Dá pra avisar a volta
mesmo com pedido não entregue (devolução, cliente fechado): o botão não espera a carga acabar.
🕐 E o percurso fecha. Ele ganhou o tempo da última parada de volta pra fábrica e o
total da viagem, da saída até voltar. A volta é o único passo que acontece DEPOIS da última
entrega — deduzir o dia dela pra trás, como se faz com a saída, jogaria o caminhão pro dia anterior; por
isso ela tem a âncora própria (quem entrega 23:30 e chega 00:40 vê 1 h 10).
🎯 De quebra, a hora deixou de ser deduzida. Cada toque agora grava o instante junto
(saidaEm/chegadaEm) — antes o app guardava só 'HH:MM', sem o dia, e o
escritório tinha que adivinhar pela entrega. E marcar a volta não apaga mais a hora exata da saída.
🚫 Carga velha continua sem a marca, e a tela diz "o motorista ainda não avisou que voltou" —
que é a verdade. Ela não passa a afirmar que o caminhão está na estrada só porque a volta não foi
marcada: seria o mesmo furo do badge em roupa nova.
🔧 Por dentro: marcarChegadaFabricaCarga + _motBotaoVoltaCarga +
cargaVoltou/cargaVoltaPendente (painel_motorista.html), ancorarDepois
e os tempos de volta no js/80-percurso-entrega.js. Grava por merge, só a chave da carga,
partindo do que já estava — nunca por cima da saída. 57 checagens · 9/9 mutações acusadas em
tests/percurso-da-entrega.test.mjs. Sem servidor e sem migration — nada pro Luan.
v2.37.753
📡 O sensor cobre quem esquece de apertar — e o Mural avisa quando a máquina roda sem pedido.
O caso do 2º turno (09/09/2026): o Arnaldo pegava o pedido no tablet e ia direto pra máquina, sem tocar
em 🔧 Ajuste nem em ▶. O automático só olhava pedido em ajuste, então de noite nada acontecia —
e o Mural ficava "LIVRE" com a Slotter a 60 caixas por minuto. Duas mudanças, as duas pedidas pelo dono:
1) Pedido só aberto no tablet também entra em produção sozinho. Com o 🤖 ligado na máquina, se o
pedido está aberto na tela (sem ajuste, sem ▶) e passam mais de 20 caixas em 2 minutos, o app inicia
a produção com o contador começando no início dessa rajada — a mesma regra do ajuste. Se OUTRO pedido da
mesma máquina já está rodando naquele tablet, as caixas são dele e o pedido só aberto não entra.
2) "⚠ RODANDO SEM PEDIDO" no Mural. Máquina com sensor contando e ninguém apontando deixa de ser um
"LIVRE" cinza: o cartão fica amarelo, piscando, escrito que o sensor conta e ninguém apontou, e o PCP recebe
um aviso na tela (um por episódio; no modo TV só o cartão pisca). Vale também com o sensor de TESTE — é
assim que a Slotter roda hoje — e a régua é o ritmo medido pelo sistema, não o número cru do aparelho.
Sem o 🤖 ligado, sem sinal do sensor ou com a máquina parada, nada muda.
Só tela, sem servidor.
v2.37.752
🔁 Quando o servidor pisca, o sistema tenta salvar de novo sozinho. Na noite de 09/09/2026 o servidor caiu e voltou de minuto em minuto, e o dono mandou três vezes a mesma janela: "NÃO SALVOU · ao salvar · 21:26 · 21:29". O aviso da v2.37.750 estava certo, mas era só aviso: não existia tentativa nova. O save só voltava a rodar se a pessoa mexesse em alguma coisa outra vez — ou seja, no exato momento em que o servidor pisca, o trabalho ficava parado esperando uma ação que ninguém disse que era necessária.
🕳️ E tinha um buraco pior embaixo disso. Enquanto a edição não sobe, uma marca interna impede o sistema de puxar a foto do servidor por cima dela. Essa marca tem uma válvula de escape de 60 segundos, pra não travar o aparelho pra sempre. Com o save falhando e ninguém tentando de novo, a válvula virava armadilha: passado 1 minuto o sistema voltava a puxar, o servidor respondia, a foto de lá descia — sem a alteração do dono — e o trabalho sumia da tela sem aviso nenhum. O sistema apagava sozinho justamente o que o aviso vermelho mandava proteger.
⏱️ Agora ele insiste, e sozinho. Tenta de novo em 5 s, 15 s, 30 s, 1 min e daí de minuto em minuto, renovando a marca a cada tentativa — então a válvula não estoura no meio do caminho e nada é sobrescrito. O aviso passou a mostrar a conta: "NÃO SALVOU — tentando de novo em 15s (2ª)", e a janela do clique diz pra deixar a aba aberta. Na primeira tentativa que passa, tudo destrava junto e o aviso vira verde.
🚦 Só insiste no que adianta insistir: servidor fora, sem internet, erro 5xx, "ocupado" (429) e estouro de tempo. Acesso recusado (401/403), rota que não existe (404) e conflito (409) não melhoram com repetição — nesses o sistema para na hora e o aviso fica na tela esperando decisão.
🔧 Por dentro: _saveVaiAdiantarTentarDeNovo(), _saveAgendarNovaTentativa() e jpPararRetrySave() em js/02-firebase.js; a marca jp_sync_pendente renovada a cada tentativa (é ela que segura o iniciarPollingApi). 36 checagens + 6 mutações em tests/aviso-sinc-clicavel.test.mjs. Só navegador — nada pro Luan.
v2.37.751
🗺️ Clicou no "Entregue", abre o PERCURSO daquela viagem. Pedido do dono (09/09/2026), olhando a carga do
REGINALDO (ATN-5I22, 3/3 entregues): "quero clicar no entregue e ele abre a hora que o motorista saiu,
chegou no cliente — um percurso que aconteceu... tipo tempo de espera".
⏱️ Na "Entregas ao vivo", cada linha de cliente virou um clique. Abre a viagem em ordem:
🏭 saiu da fábrica → 🛣️ tempo até o cliente → 📍 chegou → ⏳ tempo PARADO no cliente
(espera + descarga) → ✅ entregou, parada por parada, com o total porta a porta no rodapé.
Numa carga de várias entregas, cada trecho conta da parada anterior — não da fábrica de novo.
🌙 A conta funciona com a viagem virando a noite. É o caso do print: saiu 01:10, entregou 10:17.
O app do motorista grava a entrega com dia e hora, mas a saída e o "📍 cheguei" só com a
hora — então o dia é deduzido pela entrega daquela parada, voltando um dia quando precisa. Quem sai
23:40 e entrega 01:30 agora vê 1 h 50, e não 22 horas nem um número negativo.
🚫 Não inventa e não conclui na dúvida. Conta que passaria de 12 h sai com ⚠️ (aí a dedução
do dia pode ter errado) e conta negativa não é estampada. Devolução continua sendo devolução (com
o motivo), e entrega desfeita pelo escritório aparece como desfeita — nenhuma das duas vira entrega.
Pedido que falta entregar não se junta com o que já foi, mesmo sendo do mesmo cliente.
🏁 E diz o que NÃO sabe: a hora em que o caminhão voltou pra fábrica aparece em branco com a
explicação — esse botão existe só na viagem da escala, nunca na carga, que é o caminho que a
fábrica usa. Campo vazio sem explicação parece defeito; assim é informação.
🔒 Nada é gravado. Tudo é derivado do que o celular do motorista já sobe (porCarga e
porPedido no doc entregas_status) — aqui é só leitura, a mesma trava da
v2.37.736. Sem servidor, sem Luan, sem migration: é recarregar a página.
🔧 Por dentro: js/80-percurso-entrega.js (montar/ancorar/dur,
puros) e o clique data-ev-percurso no evCardCarga/renderEntregasVivo
(js/08). 34 checagens · 6/6 mutações acusadas em tests/percurso-da-entrega.test.mjs.
v2.37.750
🖱️ "Falha ao sincronizar" agora ABRE quando você clica — e diz se o seu trabalho subiu ou não. Queixa de 09/09/2026: "quero saber por que fica falha ao sincronizar, quero clicar para saber o que está acontecendo". Era um beco sem saída: a frase aparecia, não explicava nada, não dava pra clicar, e o motivo real morria no console — que o dono não abre.
🕵️ Por que só esse aviso era cego. O sistema tem três momentos de conversa com o servidor: buscar novidades, salvar o que você fez e publicar a lista pro tablet do operador. A v2.37.358 já tinha dado motivo e evidência guardada pro buscar — e o salvar ficou de fora, escrevendo a frase genérica sem detalhe nenhum. Pior: por não mandar detalhe, ele ainda apagava a explicação que o buscar tinha deixado. A falha mais grave das três — a que significa "o que você acabou de fazer não subiu" — era justamente a única que não deixava rastro.
🚦 Agora o aviso diz QUAL metade falhou. Se foi ao salvar, ele fala "NÃO SALVOU", porque aí a alteração ainda está só nesta tela e fechar a aba perde o trabalho. Se o pedido foi salvo e só a publicação pro operador tropeçou, ele fala "salvou aqui, mas o operador não recebeu" — dado que estava salvo não é mais anunciado como perdido, e lista velha no tablet não passa mais por "está tudo certo". Antes as duas coisas tinham a mesma cara.
👆 Clicar abre uma janela em português. Ela responde, nesta ordem: o seu trabalho se perdeu ou não, de quem é o problema (sua internet, este navegador, ou o servidor) e o que fazer agora — inclusive dizendo, com todas as letras, quando é caso de chamar o Luan em vez de mexer no seu computador. Embaixo ficam os detalhes técnicos e um botão 📋 Copiar, porque hoje o jeito de me contar um erro é fotografar a tela, e foto corta texto. O balão de mouse continua existindo, mas tablet e celular não têm mouse — era por isso que a explicação nunca chegava em quem estava na fábrica.
🤫 A faxina do navegador ficou calada. Pedido do dono: "limpa o cache, mas não precisa aparecer que está limpando". O que a faxina descarta é só cópia que o servidor reescreve no carregamento seguinte — não houve perda nem decisão a tomar, então o aviso não pedia ação nenhuma e só gastava a atenção que os avisos de verdade precisam. O registro continua inteiro no console, e o aviso de "não consegui limpar" continua aparecendo: aquele não é "estou limpando", é um problema que só a pessoa resolve.
🗄️ E a faixa "NUNCA FOI FEITO BACKUP" saiu da tela. Ela cobrava um backup todo dia dizendo "você tem 360 pedidos guardados SÓ NO NAVEGADOR" — o que era verdade quando o sistema inteiro morava no navegador, e deixou de ser quando os pedidos passaram a viver no banco de dados. Cobrar todo dia contra um perigo que não existe mais é o jeito mais rápido de ensinar a ignorar aviso, e a atenção do dono é necessária pros avisos que importam — o "NÃO SALVOU" desta mesma versão, por exemplo. O botão ☁️ Backup continua lá e funcionando: só a cobrança automática saiu.
🛟 Dito com todas as letras: aquele backup nunca foi a rede de segurança de verdade — ele gera um arquivo guardado dentro do mesmo banco que deveria proteger, e cobre só pedidos, caixas, clientes e snapshots (a produção apontada pelos operadores, bobinas, papel, compras e manutenção nunca entraram nele). O backup que presta é o pg_dump do servidor (scripts/backup-banco.sh), e esse é com o Luan.
🧯 Junto veio um para-raios no servidor. Medido na queda de 09/09: /api/ping, que não toca o banco, respondia em 0,2 s; /api/health, que toca, pendurava 40 s e morria em 502/504. O motivo de um engasgo do banco derrubar o sistema inteiro era o pool sem nenhum prazo pra desistir: cada tela que pedia dado entrava numa fila infinita até derrubar o processo — inclusive o login. Agora tem prazo (8 s pra conseguir conexão, 30 s por consulta), então o mesmo tropeço vira uma tela avisando o erro em vez de todo mundo fora do ar. Isso não conserta a causa — por que o banco travou continua sendo pro Luan olhar (pm2 logs no minuto da queda, pg_stat_activity × max_connections, disco do servidor).
🔧 Por dentro: fase salvar/publicar separadas no salvarPedidosFirebase, jpGuardarFalhaApi passando a valer também no salvar, atualizarStatusSinc ligando o clique quando há o que mostrar, e jpAbrirFalhaSinc — tudo em js/02-firebase.js; toast de sucesso removido do js/91-espaco-livre.js; faixa desligada no atualizarBannerBackup() (js/01, função inteira preservada); prazos do pool em api/src/db.js. ⚠️ Precisa do Luan: pm2 restart (é a API). Sem migration.
v2.37.749
🧹 "Sem espaço no navegador" — não parava de aparecer. Agora parou, e pela raiz. Queixa de 09/09/2026: "não para de aparecer isso", "já colocamos um limpador, não quero que acumule", "está enchendo o meu navegador". Limpar os dados do site resolvia por alguns minutos e o aviso voltava.
📏 Por que voltava: NÃO CABIA. Antes de mexer numa linha, medimos o que o sistema manda pro navegador guardar: a carteira de pedidos tem 1,39 MB de texto, o cadastro de caixas 1,11 MB e o de clientes 0,15 MB. O Safari cobra 2 bytes por caractere e dá ~5 MB pro site inteiro — essas três cópias sozinhas pediam 5,3 MB. Ou seja: o cofre nunca coube, e cada limpeza era enxugar gelo — o servidor rebaixava tudo de volta no mesmo instante e enchia de novo. Não era sujeira; era tamanho.
🗜️ O conserto: a cópia local passou a ser guardada ESPREMIDA. As mesmas três cópias, com o mesmo conteúdo, ocupam agora 0,58 MB em vez de 4,71 MB (medido com o dado real de produção: 7× a carteira, 10× as caixas). O aparelho sai de 105% do cofre para ~12% — sobra espaço pros ~20 painéis que dividem o mesmo armazenamento. Nada muda na tela: o texto volta byte a byte igual ao que entrou, e cópia gravada por versão antiga continua sendo lida do mesmo jeito, sem conversão nenhuma.
📐 O sistema também parou de chutar o tamanho do cofre. A faxina automática (v2.37.720) tinha um teto de "5 milhões de caracteres" e por isso nunca disparava sozinha num Mac — o Safari já recusava lá pelos 2,6 milhões, muito antes. Agora o teto é o do navegador de verdade e, na primeira vez que ele recusar, o aparelho anota o próprio tamanho e passa a se cuidar por essa medida. Junto: a folga preventiva, que só olhava no boot, passou a olhar de 5 em 5 minutos — quem abre o sistema de manhã e deixa o dia inteiro não chega mais no teto à tarde, no meio do trabalho.
🗣️ E o aviso passou a dizer a verdade certa. Navegador cheio e navegador que bloqueia os dados do site (aba privada, "impedir rastreamento", cookies barrados) davam a mesma frase — "limpe os dados do site" — e no caso do bloqueio limpar não resolve nada. Agora cada caso tem a sua frase, o balão explica o que fazer, e o aviso do rodapé não se repete a cada poucos segundos (no máximo de 10 em 10 minutos). Passando o mouse por cima, o sistema ainda mostra quais cópias estão ocupando mais espaço.
🛟 O que NÃO mudou: nada é apagado do servidor — a cópia local sempre foi só um atalho, e o dado de verdade continua no banco. A faxina continua sem encostar em nada que ainda não subiu (edição de pedido, apontamento do operador, carga em montagem, ocorrência, recebimento do vendedor). Se a cópia espremida vier estragada, o sistema trata como "não tenho cópia" e busca no servidor — nunca mostra meia verdade.
🔧 Por dentro: js/88-cache-espremido.js (LZW + empacotamento em 15 bits, sem biblioteca), jpGravarLocal/jpLerLocal e jpAvisoDeCache (js/02), teto medido e folga periódica no js/91-espaco-livre.js, leitura pelo loadStorage (js/01) e _cadLerLocal (js/08). 48 checagens + mutação em tests/cache-espremido.test.mjs (as 30 do tests/espaco-livre-sozinho.test.mjs continuam verdes). Sem servidor e sem migration — nada pro Luan.
v2.37.748
📲 Página de instalar os apps no celular: instalar.html. Um link só pra mandar no WhatsApp: instalar.html mostra o menu com os 17 apps; instalar.html?app=motorista vai direto no do motorista, com o botão INSTALAR no Android, o passo a passo no iPhone (Compartilhar → Adicionar à Tela de Início) e o aviso quando o link foi aberto dentro do WhatsApp (ali não instala — tem o botão pra abrir no Chrome/Safari). Se o app já está instalado, ela diz e abre.
🔍 Revisada antes de subir: a 1ª versão (05/09, ficou sem commit) montava um manifesto próprio com ícone desenhado no código — o app instalado por ela parecia o do painel mas não era o mesmo, e o celular podia acabar com dois ícones. Agora ela usa o mesmo arquivo de manifesto que cada painel usa (manifest-<app>.json): mesmo ícone, mesma identidade, um ícone só. Entraram Ponto, RH e o Sistema, que faltavam; DRE e Conciliação ficam de fora (são do computador).
🔧 Por dentro: 9 checagens + 2 mutações em tests/instalar-app.test.mjs (todo app do catálogo tem painel e manifesto; o start_url bate; nenhum manifesto inventado; todo painel instalável está na lista). Só arquivo estático — sem Luan.
v2.37.747
🔒 A API só responde ao navegador vindo do próprio site. Até aqui ela aceitava chamada de qualquer site (o CORS refletia qualquer origem). Como o token da API fica no navegador, qualquer página da internet podia falar com a API usando o navegador de quem a visitasse (achado da auditoria de segurança). Agora só https://grupomahnat.com.br passa. Sensor de contagem, o app instalado e chamadas sem navegador continuam funcionando: CORS é regra de navegador. O dono abrindo o sistema local (localhost em qualquer porta) continua passando; página aberta por arquivo (file://) não. Domínio a mais (ex.: www.) entra pelo .env, sem mexer no código: CORS_ORIGENS=https://www.grupomahnat.com.br.
🔧 Por dentro: origemPermitida() em api/src/index.js; 8 checagens + 3 mutações em tests/cors-fechado.test.mjs. Feito em 08/09 como "742" numa sessão que não chegou a subir; revisado (a versão de lá barrava o dono local fora da porta 3001).
⚠️ Precisa do Luan: pm2 restart all (é a API). Se algum painel parar de falar com a API depois disso, o motivo é o domínio: conferir se abre por https://grupomahnat.com.br mesmo (sem www., sem http://) — ou pôr a variação no CORS_ORIGENS.
v2.37.746
🏛️ Agora é o SERVIDOR que manda na lista do operador — e ele não adivinha, ele pergunta. A v2.37.745 pôs a trava nas telas, e ela funciona; só que uma aba velha esquecida aberta em qualquer computador continuava publicando sem carimbo e limpando a lista do tablet — e ninguém na fábrica tem como saber disso. Esta é a camada que vale pra todos os aparelhos, hoje e amanhã.
🔎 O servidor tem a verdade na mão: a tabela de pedidos. Quando chega uma lista em que um pedido sumiu, ele consulta o pedido no banco e pergunta: este pedido ainda é da fábrica? Se o banco diz que sim — material disponível com chapa, reprogramado com chapa, ou em produção — o pedido fica publicado, não importa quem mandou a lista nem quão velha é a tela. Não é palpite, é consulta.
✅ Tirar continua funcionando. Ficou pronto, foi carregado, entregue, perdeu a chapa, foi excluído: o banco concorda e o pedido sai na hora. Pedido excluído não ressuscita — ele nem tem linha no banco pra consultar.
🚪 E o que CHEGA nunca é barrado — é por ali que pedido novo aparece pro operador. A trava é só contra apagar: sumir da tela do operador é o estrago que ninguém desfaz; pedido a mais na lista o publish seguinte tira, e o app já filtra por máquina e por etapa.
🔒 A leitura do que está publicado é feita com a linha travada (FOR UPDATE), então dois PCP publicando no mesmo segundo não leem a mesma foto. E se a proteção não puder rodar por qualquer motivo, a publicação acontece do mesmo jeito — travar a fábrica por causa da trava seria pior que o problema.
🧰 Este precisa do Luan: é mudança de API. pm2 restart no servidor. Sem migration — nenhuma tabela nova, nenhuma coluna nova; só uma consulta a mais quando a lista chega faltando alguém.
🔧 Por dentro: _protegerListaDoOperador + _gravarSnapshot (api/src/routes/snapshots.js), com a régua de publicação espelhando a do PCP (js/02-firebase.js). O PUT e o /sync passaram os dois pela mesma porta. 24 checagens · 6/6 mutações acusadas em tests/servidor-protege-lista-do-operador.test.mjs, com o Postgres dublado (não precisa de banco pra rodar).
v2.37.745
🖥️ Um PC do PCP não reescreve mais o que o outro fez. Palavra do dono (09/09/2026): "aqui está chapa disponível e no app não está — ele fica sumindo e aparecendo", e depois: "um não pode reescrever o outro". Na Carteira a chapa estava lá (2.000 ✓, 8.000 ✓) e no tablet o pedido ia e voltava.
🔎 A Vida do Pedido provou onde NÃO era. No 24063 · 01.02 o histórico tem duas linhas e mais nada: "04/09 entrou pela importação" e "09/09 15:56 chapa lançada: 8.000 → material disponível". Nenhuma reversão, nenhuma reprogramação, nada tocou o pedido. Ou seja: o problema nunca esteve no pedido — estava na lista que o PCP publica pro tablet.
🧨 A raiz: "o último que salvou manda". A lista do operador é reescrita INTEIRA a partir da memória de quem chamou — e isso acontece a cada save, em qualquer aba e qualquer PC do PCP. Basta um deles ainda não ter recebido a chapa (entre dois polls, ou uma aba aberta desde cedo) pra ele publicar a lista sem o pedido: some da fábrica. O PC atualizado publica de novo: volta. Com os dois abertos, pisca para sempre — sem ninguém ter errado nada.
🛡️ Agora quem vai APAGAR tem que provar que é mais novo. É a mesma régua das barreiras do sync: carimbo. Se eu tenho o pedido mas com carimbo mais velho que o publicado, ou se a minha carteira inteira é mais velha que a de quem publicou, eu é que estou atrasado — e o que está no ar fica. Só tira quem tem decisão nova de verdade (ficou pronto, carregou, perdeu a chapa). Se conserta sozinho: quando o atrasado sincroniza, os carimbos se igualam e o pedido sai normal.
🔀 E duas publicações da MESMA aba pararam de se atropelar. A função lê a nuvem, só depois recorta a carteira e por fim grava — e nesse meio o polling pode ter trocado a carteira inteira. Sem fila, uma chamada que começou antes gravava depois, botando a foto velha por cima da nova. Agora elas entram em fila e a segunda refaz o recorte com o estado já atualizado.
⚠️ Tem que recarregar TODOS os PCP. Uma aba na versão antiga continua publicando sem carimbo e continua limpando a lista — a trava só vale entre telas já na v2.37.745. Se um computador esquecido ficar aberto na versão velha, o pedido continua piscando.
🔧 Por dentro: publicarPedidosParaOperador (js/02-firebase.js) — o pedido publicado passa a levar _chapaEditadaEm e a publicação leva baseEm (relógio do servidor, não do PC). A trava de segurança da v2.28.6 (carteira vazia não zera a fábrica) continua de pé. 12 checagens · 6/6 mutações acusadas em tests/publicacao-operador-nao-apaga.test.mjs, com o atropelo de concorrência reproduzido de verdade. Sem servidor, sem migration.
v2.37.744
📋 "Eu ponho MATERIAL DISPONÍVEL e ele sai sozinho." Queixa de 09/09/2026: o PCP lançava a chapa várias vezes no mesmo dia e o pedido voltava pra Esperando programação sozinho — e no tablet do operador os pedidos apareciam e sumiam, tocando o sino a cada volta. Era a mesma coisa nas duas telas: alguém estava zerando a chapa. Sem chapa, o pedido cai do filtro que alimenta o operador e some da fábrica; e no PCP a tela passa a escrever "Esperando programação", porque é assim que ela chama todo material disponível sem chapa (o status no banco nem tinha mudado).
✂️ Quem zerava: a reprogramação automática da v2.37.729. Aquela versão pôs a régua certa — "a chapa acabou (±10%) ⇒ reprograma" — mas só no tablet. Aqui no PCP o gatilho continuou sendo apenas "falta pedido", sem olhar a chapa. E a conclusão que chega aqui nem sempre é o operador fechando agora: de 5 em 5 segundos o sistema relê a lista publicada, que carrega marca de "concluído" que a publicação nunca rebaixa. Marca velha + falta de pedido = reprogramava e jogava fora a chapa recém-lançada. No caso real (pedido 24063 DEUSA ALIMENTOS) eram 2.000 chapas com ZERO caixa produzida — a chapa não tinha acabado coisa nenhuma; estava no chão.
✅ Agora as duas telas usam a MESMA régua (duas réguas pra mesma pergunta foi como isto nasceu): chapa lançada × poses, folga de 10% com piso de 50 cx. Ainda tem chapa? Não se toca em nada — nem status, nem chapa, nem etapas: o pedido fica na lista pro próximo operador continuar, exatamente a palavra do dono na v729. A chapa acabou? Reprograma sozinho, como a v729 desenhou. E nunca mais carimba "PRONTO" num pedido que não fez a quantidade.
🔁 Junto, o "programei e voltou" fechou de vez. O pedido de reprogramar que o operador mandava (canal antigo, hoje sem botão) podia ser reaplicado depois: o marcador de "já apliquei" reinicia a cada F5, e sinal de pedido que ainda não estava carregado nunca era marcado. Assim que o PCP lançava a chapa e o pedido andava, o sinal velho voltava e zerava tudo de novo. Agora vale a ordem dos acontecimentos: se o PCP mexeu depois do pedido do operador, o sinal está respondido — marca como aplicado e não encosta no pedido.
🔔 E o sino do tablet parou de assustar a fábrica. O aviso "novos pedidos" é calculado por diferença entre uma publicação e a seguinte, e a lista é reescrita inteira por qualquer PC do PCP que salve — então o mesmo pedido tocava, vibrava e piscava a cada ida e volta. Pedido que estava na lista nos últimos 30 minutos não é "novo". Isto é o cinto, não o conserto: a causa está resolvida acima. Não filtra a lista — nenhum pedido é escondido, só o sino é que cala.
🛟 O que NÃO mudou: a folga do pedido continua 5%, a da chapa continua 10%, pedido carregado ou entregue não é tocado, produção nunca é anulada e todos os botões do PCP (inclusive o 🔄 Reprogramar · falta) continuam onde estavam — saiu o automático errado, não a escolha de ninguém.
🔧 Por dentro: processarFinalizacaoPedido e aplicarReprogramarOperador (js/02-firebase.js), _sinoEhNovoMesmo (painel_operador.html), sobre o caixasDaChapaLancada que já existia (js/01). 34 checagens · 10/10 mutações acusadas em tests/reprograma-sozinho-quando-a-chapa-acaba.test.mjs, com o caso real do 24063. Sem servidor e sem migration — nada de API, nada pro Luan: é só arquivo estático, e o cache-bust já obriga o tablet a baixar a versão nova.
v2.37.742
📦 A coluna "Produto/Cód." passou a mostrar o nome da CAIXA. Pedido de 09/09/2026: "o que eu quero que fica igual é o nome da caixa, seja o produto/cód — o resto mantém como estava". O que o pedido guarda é o texto do Sectra (TIPO 04 SEM IMPRESAO); o cadastro é escrito à mão (TIPO 04 SEM IMPRESSAO). Agora as quatro telas que têm essa coluna — Relatório, PCP, Entregas e Velocidades — mostram o nome do cadastro.
🩹 Por que a v2.37.741 não bastou. Ela faz o nome do cadastro descer pro pedido quando alguém renomeia a caixa, mas só alcança o pedido que está ligado a ela — e o pedido de nome errado é justamente o que não tem vínculo nenhum (o nome é o único elo, e é ele que está errado). Na tela isso aparecia como "mudo a caixa e não muda nada", sem aviso nenhum. Aqui a caixa é achada pela régua da casa (a mesma que a programação, a paletização e o romaneio já usam): vínculo direto manda; sem ele, código + mesmo cliente, aceitando os apelidos de sempre (KININO 22 ↔ CX 22). Não achou com segurança → mostra o que está gravado, como antes. Caixa de outro cliente nunca empresta nome.
🛟 Isto é só a TELA — o resto ficou como estava. Não grava, não muda o pedido, não mexe em romaneio, etiqueta, nota, estoque nem no que o tablet do operador recebe. E o texto do Sectra não some: quando os dois são diferentes, ele aparece ao passar o mouse na célula — quem procura pelo nome do relatório continua achando.
🔧 Por dentro: jpNomeProdutoCod + jpCelulaProdutoCod (js/01), sobre o fpCaixaDoPedido que já existia; as 4 colunas col-codigo passaram a chamar a mesma célula. 16 checagens e 5 mutações em tests/coluna-produto-cod-mostra-a-caixa.test.mjs, incluindo a do fio (coluna que ficar pra trás fica vermelha). Sem servidor, sem Luan.
v2.37.741
📦 O nome do pedido virou o nome da caixa — corrigiu no cadastro, corrigiu na carteira inteira. Até hoje o nome que aparece no pedido era uma cópia morta, tirada do cadastro na hora de lançar: arrumar a referência da caixa não chegava em pedido nenhum, e é o pedido que vira palete, etiqueta, romaneio e nota. Era assim que a POWERDENT ficava com TIPO 04 SEM IMPRESAO na tela com o cadastro já certo.
✏️ Agora, ao salvar a caixa com outro nome, todos os pedidos dela mudam junto e a tela avisa quantos foram. Só os DELA: vale o vínculo forte da caixa e, sem ele, código exato e do mesmo cliente — caixa de outro cliente com o mesmo código nunca é tocada.
🛟 Nada se apaga (REGRA ZERO). O nome velho fica no histórico de cada pedido (quem mudou, quando, de quê pra quê) e na ficha da caixa. Palete, etiqueta e romaneio já impressos continuam como saíram — papel que foi pro cliente não se reescreve.
🔗 E a importação do relatório não desfaz mais. O relatório do Sectra continua mandando em data, valor, quantidade e observação — só o nome saiu dessa regra, para o pedido vinculado a uma caixa cadastrada. A caixa renomeada continua sendo achada pelo nome antigo do Sectra (senão todo pedido novo dela cairia em "caixa não encontrada", sem herdar o roteiro e sem atualizar o preço), e o pedido que casou só pelo nome ganha o vínculo forte na hora.
⚠️ Cuidado que ficou coberto: o pareamento da importação passou a reconhecer o pedido pelo nome que o relatório deu, não pelo da tela. Sem isso, um pedido renomeado entraria de novo na carteira na primeira mudança de data — que foi exatamente o estrago de 04/09 (11 pedidos em dobro numa importação só).
🔧 Por dentro: cxRenomearPedidosDaCaixa + codigosAnteriores (js/08, pendurados nas duas portas — salvarCaixaModal e micSalvar, o micro/cartão — e levantados pelo contarVinculosCaixa ANTES da troca); jpCodigoPedidoDoCadastro, jpProdKeyImp (chave única do pareamento, era escrita à mão em 3 lugares) e o vínculo da importação aceitando o nome antigo, com cliente exato (js/01). 39 checagens e 6 mutações em tests/nome-do-pedido-segue-a-caixa.test.mjs. Sem servidor, sem Luan. (Era pra ser a 739; a main ganhou a 739 da carga por cliente no caminho — e o selo ATUAL, que tinha ficado nela, voltou pro topo.)
v2.37.740
📄 Os três consertos do romaneio: o número que se queimava sozinho, o cancelamento que não existia e a carga que não tinha volta.
1) 🚨 "Cancelar" estava EMITINDO um número novo. Quando a carga já tinha romaneio, a pergunta era:
"OK = reimprimir a 2ª via · Cancelar = emitir um romaneio NOVO". Em qualquer tela do mundo
"Cancelar" quer dizer deixa pra lá — quem abria o romaneio só pra conferir e tocava ali
queimava um número e criava mais um papel do mesmo embarque. Medido no servidor em 08/09/2026: a
POWERDENT saiu com os números 60, 63 e 68 — a mesma carga, o mesmo palete — e o FK GRUPO
com o 58 e o 66.
✅ Agora é uma tela com três botões que dizem o que fazem: 🖨️ 2ª via do Nº 60 ·
➕ Emitir NOVO — Nº 69 · ✖ Fechar sem imprimir. Fechar (e clicar fora, e o Esc) não emite
nada. E o número que aparece no botão é o que sai de verdade — olhar não queima número.
2) ❌ Agora dá pra CANCELAR um romaneio. No 📄 Histórico de romaneios, cada papel tem o botão
❌ Cancelar: pede o motivo (sem motivo não cancela) e marca quem cancelou e quando. O romaneio
fica na lista riscado, em vermelho, com o motivo à vista — nada é apagado e nenhum número é
reusado, porque o número precisa continuar explicando o buraco na sequência (e o cliente pode estar com
aquele papel na mão). A 2ª via de um cancelado sai com a tarja vermelha "ROMANEIO CANCELADO — NÃO
VALE", e ele deixa de liberar o pedido pro faturamento: papel cancelado não vira nota.
3) ✏️ Corrigir uma carga JÁ FINALIZADA. No Histórico de Cargas, o botão ✏️ Corrigir
carga abre a lista dos paletes: ✖ tirar devolve o palete ao Estoque PA (o mesmo ↩ de
sempre, com nome e hora) e ➕ pôr na carga traz um palete do PA. Nos dois casos o romaneio daquele
cliente é cancelado com o motivo escrito, e o novo sai pelo botão 📄 de sempre. Os totais da carga
(paletes, caixas e peso) são recalculados, e cada mexida fica registrada na carga com quem, quando
e por quê.
⚠️ Quem corrige é o PCP, no sistema — decisão do dono. O app da
Expedição ganhou a trava na versão passada (palete de outro cliente não entra); aqui é o conserto do
que já passou, e ele mexe em estoque e em documento.
⚠️ O que já foi ENTREGUE não se mexe: se o motorista confirmou a entrega daquele pedido, a tela diz
"✅ entregue — não mexe" e o botão nem aparece. Reescrever o que aconteceu não é correção — ali o caminho é a
devolução.
⚠️ Na dúvida, não grava: a carga só é regravada depois de reler a lista do servidor (o
documento é uma lista só — foi assim que 6 romaneios sumiram em 21/08). Sem responsável identificado ou sem
motivo, nada acontece.
🔧 Por dentro: romEscolherRomaneio, romCancelarRomaneio,
_romNumProximoPreview (js/24) · tarja no js/54 · módulo novo
js/79-corrigir-carga.js (usa o spEstornar/spGravarSaidas do js/30 —
estoque continua tendo um dono só). 20 checagens e 5 mutações em
tests/romaneio-cancelar-e-corrigir-carga.test.mjs. Sem servidor, sem Luan.
v2.37.739
🚫 Palete de outro cliente não entra na carga — dois bips e a tela vermelha.
O que aconteceu (08/09/2026). A carga do REGINALDO (AOR4231) era do EMPORIO PRIME, e
dentro dela foi bipado o palete TIPO 02 SEM IMPRESSAO da POWERDENT (1.513 cx, pedido
23749). O app aceitou numa boa — bip verde, aviso verde — porque nada olhava o cliente. O erro
só apareceu no romaneio, com a mercadoria já no caminhão.
✅ Agora a carga sabe de quem ela é. Na tela Nova Carga tem o campo 🏢 Cliente desta
carga, com a lista de quem tem palete pronto no PA (e quantos). Enquanto ele bipa, o nome do cliente
fica ao lado da placa, junto com a data da entrega.
🚫 Palete de outro cliente é BARRADO: dois bips graves (o som que faz parar e olhar, o mesmo
do "fora do planejamento"), a tela inteira vermelha com "NÃO É DESTE CLIENTE", de quem é o palete e
de quem é a carga — e ele não entra. Vale pro QR e pra marcação manual, que passam pelo mesmo lugar.
➕ E quando a carga é MESMO de dois clientes? Acontece: das 52 cargas com palete do histórico,
4 levam mais de um cliente (uma delas é justamente o erro de hoje). Depois de barrar, aparece o botão
"➕ Este cliente também vai nesta carga", que pergunta antes de aceitar. Trava sem saída faria o
conferente parar de usar o app — e app que atrapalha vira app que se contorna.
⚠️ A trava não trava a fábrica: carga antiga, ou carga aberta
quando o estoque do PA não carregou, aceita tudo como sempre (e a tela avisa que a trava está desligada).
Carga que vem da escala já nasce com os clientes dos destinos da viagem — ali não se pergunta de
novo. E a comparação de nome é a mesma régua do romaneio: "TANGARA" e "tangara" são o mesmo
cliente, senão a trava barraria por causa de uma letra (§v2.37.730).
🔧 Por dentro: cargaAceitaCliente, cargaAdicionarCliente,
popularClientesDaCarga e o aviso outroCliente (painel_expedicao.html);
clientes[] na carga. 13 checagens e 4 mutações em
tests/carga-so-do-cliente.test.mjs. Sem servidor, sem Luan.
v2.37.738
🚚 App do motorista: uma parada é um LUGAR, não um pedido. A FK GRUPO saiu na mesma carga com dois pedidos pro mesmo endereço em Bariri e a tela pedia "Cheguei" e "Entreguei" duas vezes no mesmo portão. Agora os pedidos do mesmo cliente no mesmo endereço viram uma parada só, com o total de paletes e caixas, "Entreguei os 2" e a rota contando certo. Sem endereço cadastrado, cada pedido fica na sua parada e a tela avisa.
🔁 DEVOLUÇÃO do pedido (pedido do dono: "tem caso que os pedidos voltam"). Botão "Cliente devolveu — volta pra fábrica" em cada pedido que ainda não foi entregue. Pede o motivo (obrigatório: recusou, avaria, fechado, pedido errado…). Devolver não é entregar: o escritório NÃO marca Entregue; ele grava a devolução no pedido (motivo, quem, quando), põe no histórico, avisa na tela e o pedido ganha o selo 🔁 devolvido. O que fazer com as caixas que voltam é decisão do PCP/expedição, como sempre.
↩️ Desfazer entrega ou devolução marcada por engano, com rastro (a hora vai pra "desfeito", nada é apagado). Entregas ao vivo no escritório mostra o 🔁 devolvido com o motivo, e o histórico do motorista também.
🔧 Por dentro: paradasDaCarga, marcarChegadaParada, confirmarEntregaParada, devolverPedidos, desfazerEntregaParada (painel_motorista — uma gravação por parada, {merge:true}, só as chaves dela); jpSincronizarEntregasMotorista lê devolvidoEm (js/08); jpSeloEntregueEm (js/01). 30 checagens + 4 mutações em tests/motorista-paradas-e-devolucao.test.mjs. Sem servidor, sem Luan. (A parte das paradas era a "729" que ficou sem commit numa worktree, com os botões apontando pra função que não existia.)
v2.37.737
⚠️ "As ocorrências que os operadores lançam não aparecem no sistema" — e não apareciam mesmo, desde 28/08.
Nada se perdeu. Conferido no servidor hoje (08/09/2026): tudo que o operador registrou está
lá. O depósito onde os tablets gravam tinha 129 ocorrências e a última entrou hoje às
14:56 (POWERDENT, chapa abaulada, 310 cx, Máq. B). Quem estava cego era a tela.
A causa. Na v2.37.587 a lista velha foi congelada de propósito — ela era gravada inteira
por três aparelhos ao mesmo tempo e um apagava a ocorrência do outro. Toda gravação passou pro
depósito novo, uma ocorrência por vez. Só que o leitor do depósito novo foi criado e
nunca ligado: a tela continuou lendo só a lista congelada, parada nos 112 registros de 28/08 às
11:49 — a hora exata em que ela foi congelada. Daí o sintoma: o tablet diz "registrada", o servidor
recebe, e no sistema não aparece nada. Sem erro, sem aviso, sem tela vermelha.
✅ Agora aparecem as 18 que faltavam — 1.819 caixas, 10 delas de setembro,
incluindo as três de hoje. E não era só a tela de Ocorrências: Perda por Etapa,
Ficha do Operador e Vida da Caixa leem a mesma lista — os três estavam sem essas perdas.
⚠️ Os relatórios de perda vão subir. São
1.819 caixas que sempre existiram e não estavam sendo contadas — não é perda nova, é
perda que estava escondida.
🔧 Por dentro: _ocKeyApi.iniciar() no initOcorrenciasModule (js/08) —
o fio que faltava. 28 checagens e 5 mutações em
tests/ocorrencias-nao-se-perdem.test.mjs, sendo 3 novas que medem o FIO e não só a
conta (as antigas passavam com o defeito no ar, porque injetavam o depósito na mão). A última
delas vale pra qualquer tela: leitor de dado criado e nunca ligado agora é teste vermelho.
Sem servidor, sem Luan.
v2.37.736
🚛 "A carga ao vivo não está aparecendo aqui" — a tela do escritório estava cega.
Print do dono (08/09/2026): a aba Entregas ao vivo, na data de hoje, dizendo
"Nenhuma viagem com motorista nesta data" — com dois caminhões na rua. O LUCIANO
(FBW-4G22) já tinha marcado no app "saí da fábrica 11:35" e "cheguei" nos dois pedidos do FK
(11:55 e 11:56), e o REGINALDO (AOR4231) já tinha confirmado 6 entregas.
A causa. Essa tela só sabia ler viagem da ESCALA — e a escala quase não é usada: o sistema
inteiro tem 4 viagens, todas de agosto (15, 18 e 21), nenhuma de setembro. O app do motorista
foi virado pra CARGA lá na v2.37.336 ("a viagem é o caminho antigo e depende do PCP montar a escala;
a CARGA é o que existe de verdade"), e o escritório ficou olhando pro lugar vazio. Pior que tela sem
informação é tela que afirma que não tem ninguém rodando.
✅ Agora a tela mostra as CARGAS do dia — uma por caminhão, com o que o motorista marcou no app:
🚚 Saiu 11:35, o estado de cada cliente da carga
(🚗 A caminho · 📍 No destino · 11:55 ·
✅ Entregue · 10:30), o placar 2/3 entregues e o
🏁 Chegou da volta. As viagens da escala continuam aparecendo — quem montar uma
vai vê-la do mesmo jeito.
📅 O dia é o que ACONTECEU nele. Carga fechada dias atrás e entregue hoje aparece hoje (com a
data do fechamento no card) — foi o caso das 6 entregas do REGINALDO. Caminhão que está na estrada agora
vem em cima da lista, e o número da aba conta só quem saiu e ainda não voltou.
⚠️ Não inventa nada: sem marca do motorista, o cliente fica
"🚗 A caminho" e a carga diz "⏳ ainda não saiu" — mas só enquanto nada foi entregue: carga com
entrega confirmada obviamente saiu, e ali a tela diz "saída não marcada no app". Confirmação que o
escritório desfez não conta, e "📍 cheguei" (que só guarda a hora, sem o dia) não puxa carga velha
pra tela de hoje.
🚨 De quebra, um apagão que ainda não tinha acontecido: o sistema abria este documento com permissão
de escrita e mandava de volta o bloco inteiro da memória do PC — sem a parte
porCarga, que ele nem lia. Bastava um PC com carimbo adiantado no boot pra apagar as horas
de saída gravadas pelos motoristas — o mesmo caminho que comeu 6 romaneios em 21/08. Agora o documento é
só leitura aqui: quem escreve nele é o app do motorista, registro a registro.
🔧 Por dentro: evCargasDoDia, evCardCarga, evMexeuNoDia e
ENTREGAS_POR_CARGA (js/08); soLeitura no snapshot
entregas_status. 15 checagens e 3 mutações em
tests/entregas-ao-vivo-mostra-carga.test.mjs. Sem servidor, sem Luan.
v2.37.735
📅 O dia da entrega embaixo de cada pedido — e o filtro "Entregue + Hoje" mostrando o que saiu hoje.
Print do dono (08/09/2026): a carga do LUCIANO (FBW-4G22) voltou entregue, com FK GRUPO
23357 e 23359 dentro. Na Carteira, filtro Entregue + Hoje: "Nenhum pedido neste
filtro".
A causa. O filtro de período media a data PROMETIDA do pedido, nunca o dia em que a
mercadoria chegou no cliente. O 23359 foi entregue em 08/09 e estava prometido pra 04/09 —
a conta dava "4 dias atrás", então ele não era de hoje pra ninguém.
Medido na carteira de verdade no mesmo dia (365 pedidos): 3 foram entregues em 08/09 (os dois
do FK e a TANGARA 23960) e o filtro mostrava ZERO — porque nenhum pedido entregue tinha a data
prometida caindo em 08/09. E não é exceção: em 233 dos 248 pedidos entregues com data registrada, o
dia da entrega é diferente do prometido.
✅ Agora, nas duas telas (Carteira e PCP): pedido já entregue é filtrado pelo dia em que foi
entregue, e embaixo do status de cada um aparece ✅ entregue 08/09/2026,
com +4d quando saiu depois do prometido. Pedido que ainda não foi
entregue continua exatamente como era — ali a promessa é o que importa.
🚚 Antes de dizer qualquer coisa, o sistema confere o MOTORISTA. Se ele já confirmou a entrega no
app e o escritório ainda não mexeu no status, o card mostra 🚚 motorista entregou
08/09 às 13:30 — sem dizer que o pedido está Entregue, porque quem marca isso é o PCP. E confirmação
que o escritório desfez ("marcado por engano") não vale como entrega: foi o caso das duas linhas do
FK naquele dia.
⚠️ Não inventa data. Os 19 pedidos entregues antes de o
sistema guardar o dia da entrega mostram "✅ entregue · dia não registrado" — nunca a data prometida
no lugar da real. Eles continuam aparecendo nos filtros pela data do pedido, como sempre.
🔧 Por dentro: jpDataEntregueReal e jpSeloEntregueEm (js/01),
jpEntregaDoMotorista (js/08, só leitura do doc do motorista).
20 checagens e 3 mutações em tests/entregue-data-no-card.test.mjs; bateria inteira
rodada (266 de 267 — a única falha é a do docs/, que não existe na worktree). Sem servidor,
sem Luan.
v2.37.734
🧾 Número que não é prazo parou de virar parcela. O nome da condição de pagamento é texto livre, e era dele que saía o parcelamento. O sistema lia qualquer número escrito ali: uma condição batizada Boleto 30 dias 2026 virava duas parcelas — uma em 30 dias e outra em 2.026 dias, cinco anos e meio à frente.
😶 Por que ninguém veria: a segunda conta a receber nasce com vencimento lá longe e simplesmente some da previsão de caixa. Metade do dinheiro do pedido sumia do radar sem erro nenhum na tela.
✅ Agora: vale como parcelamento o número colado por separador (7/14/21, 28 / 35 / 42, 30-60-90) ou vários prazos plausíveis soltos (30 60 90). Plausível é de 0 a 365 dias — prazo maior que um ano não existe aqui, e é isso que separa um prazo de um ano ou código digitado junto. O filtro vale até dentro da conta: 30/60/90 - 2026 dá as três parcelas certas e descarta o 2026.
👀 E dá pra ver antes de salvar. Em 💰 Financeiro ▸ 🧾 Condições de Pagamento a lista ganhou a coluna "Como o sistema lê", e o campo de digitar mostra na hora: 7/14/21 → 3 parcelas · 7, 14, 21 dias. Nome com número estranho avisa: ⚠️ ignorei 2026 — não parece prazo. Antes só dava pra descobrir a leitura errada depois, na conta a receber.
🔒 Nenhuma condição que já existe mudou de leitura — 7/14/21 Dias, 28/35/42, 35 Dias, 30 dias e À vista estão conferidas uma a uma contra a régua antiga no teste. O prazo médio automático do cadastro também passou a sair dos mesmos números (era outra varredura própria: com o parser velho, Boleto 30 dias 2026 dava média de 1.028 dias).
🔧 Por dentro: prazos() com separador + faixa 0–365 e lerCondicao() (js/48-nota-orc.js, exportada); ccComoLe() e ccCondPreview() no js/13-custos.js, que deixou de varrer \d+ por conta própria. 237 checagens e 15 mutações em tests/parcelas-um-dono-so.test.mjs. Pro Luan: nada.
v2.37.733
🧾 O orçamento passou a dizer as parcelas uma por uma — e o papel agora FECHA. Do orçamento do GRS TOYS E DOLLS: o dono olhou Parcelado (7/14/21 Dias) R$ 3.713,66 e leu como desconto. Se quem faz o orçamento lê errado, o cliente lê errado também — e é o papel em que ele autoriza a produção.
🔍 O número estava certo, o papel é que não dizia o que ele é. Aqueles R$ 3.713,66 não são desconto nem dinheiro que o cliente tem: é o quanto do pedido ainda cabe no limite de crédito dele (limite menos o que já deve). O resto sai à vista. O total continua sendo os R$ 37.795,52 inteiros.
✅ Agora o documento mostra parcela a parcela: A prazo (7/14/21 Dias) R$ 3.713,66 e embaixo 1ª · 7 dias R$ 1.237,88 · 2ª · 14 dias R$ 1.237,88 · 3ª · 21 dias R$ 1.237,90, fechando com À vista (na entrega). O rótulo "Parcelado", que virou "desconto" na leitura, saiu. Orçamento sem limite de crédito também ganhou as parcelas — antes o cliente não via em quantas vezes ia pagar em lugar nenhum.
🔒 O limite de crédito continua sendo assunto interno — quanto ele pode dever e quanto já deve não entram no papel do cliente, e tem teste que falha se algum dia entrarem.
🧮 De quebra, dois centavos que não fechavam. O SALDO A PAGAR vinha de uma fórmula (sub × 1,15) e o TOTAL logo acima de outra (sub + sub × 0,15): iguais na matemática, diferentes em 1,7% dos casos na hora de arredondar — o papel saía com TOTAL R$ 77.532,19 e SALDO R$ 77.532,20. E Subtotal + IPI também podia não bater com o TOTAL. Medido em 400.000 sorteios. Agora a conta devolve centavo fechado e as somas fecham em todas as linhas.
🔗 Papel e dinheiro não podem discordar: a régua que divide em parcelas era só do Financeiro (js/37) e estava escondida. Copiá-la pro documento daria um papel prometendo 3× R$ 1.237,88 e o Financeiro lançando outros valores — o §9.13 de novo. Ela mudou de casa pro js/48 (o único arquivo que as três telas do documento carregam) e o Financeiro passou a chamá-la. Nenhuma conta a receber mudou de valor — o teste compara parcela a parcela contra a régua antiga.
🔧 Por dentro: prazos(), parcelas() e blocoPagamento() no js/48-nota-orc.js (exportados); totais() arredondando em centavos; js/37-contas.js chamando a régua e fail-closed sem ela. 181 checagens e 11 mutações em tests/parcelas-um-dono-so.test.mjs. Pro Luan: nada.
v2.37.732
📅 O Lançamento de Insumos parou de abrir vazio todo dia 1º — e agora dá pra CONSERTAR a nota. Entrega de 01/09 (o dono: "a tela de lançamento sumiu!"), feita naquele dia como "636" e que ficou sem commit numa worktree; a 636 da main é outra coisa. Subiu agora, conferida contra a base de hoje.
😱 O susto: dia 1º a tela abria dizendo "Nenhum lançamento neste mês · R$ 0,00". Não sumiu nada: ela mostra um mês por vez e abria no mês do relógio, vazio de verdade no dia 1º. Agosto inteiro estava lá.
✅ O que mudou: ela abre no último mês que tem lançamento e avisa ("Abri em ago/2026 — set/2026 ainda está sem nenhum"), com o caminho de volta do lado. Mês vazio diz onde está o resto ("o último foi ago/2026, com 37 lançamentos · 📅 ver ago/2026"). Assim que a pessoa escolhe um mês na mão, manda ela.
🧾 Editar a nota: na linha azul de cada nota, ✏️ abre nº, fornecedor e total e corrige a nota inteira de uma vez; ➕ volta pra dentro daquela nota pra acrescentar um item. Era o caso da nota 21888 partida em duas (seis itens na DAL COLOR e um sozinho na SILRESIN): o sistema junta por nº + fornecedor, então fornecedor errado abre nota nova com o mesmo número. Agora se corrige o fornecedor e os sete voltam pra mesma nota.
🗂 Nada é apagado e tudo fica registrado: pede o motivo e guarda quem mudou, quando, de quê pra quê, em cada item. Juntar com nota que já existe, ou tirar o nº, ele pergunta antes. O total da nota é só conferência.
🕘 De quebra: lançamento das 21h em diante vinha com a data de amanhã (relógio de Londres); no dia 31 jogava a compra pro mês seguinte. Agora é o relógio da parede.
🔧 Por dentro: CC_COMP_TOCADO, ccUltimoMesComLanc, ccEditNota, ccNotaAcrescentar, _notaIrmaos (js/13). 34 checagens em tests/nota-editar-e-mes-com-lancamento.test.mjs + 26 em lancamento-editar-auditoria. Pro Luan: nada.
v2.37.731
✅ Pedido concluído SOME da tela daquela máquina — o operador não pega de novo.
Palavra do dono (08/09/2026): "todo pedido que for concluído, tanto na Slotter quanto na
Coladeira, tem que sair da visão dele, pra não ter que pegar".
O que estava acontecendo (23960 TANGARA 05 FLOPS 92). O pedido foi reprogramado em 04/09. O
Corte e Vinco concluiu a parte dele — e o pedido voltou pra lista do Corte e Vinco. O
operador concluiu de novo. E de novo. Em 8 minutos nasceram TRÊS apontamentos idênticos de
2.103 (12:33, 12:34 e 12:35), inflando a chapa pra 7.236 num pedido de 2.196 caixas com
2.200 de chapa lançada. E o pedido nunca virava "concluído", porque quem
faltava era a Coladeira.
A causa. Havia um if(statusOp === 'reprogramado') return false seco (da v2.34.4): num
pedido reprogramado, TODAS as máquinas voltavam a enxergar o pedido — inclusive a que
já tinha terminado a parte dela naquela mesma rodada. Essa regra era a versão crua da
geração (_reiniciadoEm / reabAtiva), que veio depois e
já sabe separar "concluído da rodada ANTERIOR" (obsoleto, volta pra
máquina) de "concluído NESTA rodada" (vale, sai da máquina).
Eram três réguas pra mesma pergunta; agora é uma só.
E o ✓ do card parou de mentir. As bolinhas do trilho liam a etapa crua, sem olhar a
geração: o card mostrava ✓ Corte e Vinco → ✓
Coladeira ao lado de "PRONTO PARA INICIAR" — as duas coisas na mesma linha, uma
contradizendo a outra. Foi o ✓ falso da Coladeira que fez o operador achar que ela estava pronta e ir
refinalizar a máquina errada.
Trava mantida: pedido reprogramado sem carimbo de geração (legado) continua
voltando pra todas as máquinas. Sem carimbo não dá pra saber de que rodada é a
marca — e sumir da tela do operador é o estrago que não se desfaz.
v2.37.730
📄 O MESMO cliente saía com DOIS romaneios — só porque o nome estava escrito diferente.
Print do dono (08/09/2026), carga AOR4231: a linha do romaneio oferecia dois botões,
TANGARA e tangara. Eram 20 paletes de um cliente só, e cada papel levava um pedaço —
13 num, 7 no outro. O empilhadeirista leu os paletes e entendeu que eram duas entregas.
Onde nasceu: ao lançar o pedido, o nome do cliente foi digitado em minúsculo. O campo deu o
✓ de cadastrado (ele sempre ignorou caixa alta) e gravou a grafia digitada.
Dali pra frente o sistema tinha dois clientes: dois romaneios, dois números, e o estoque, o
relatório e o Plano de Carga vendo o cliente partido em dois.
Agora são dois consertos:
1) O campo Cliente do pedido grava o nome do CADASTRO. Digitou "tangara"? Ao sair do campo ele vira
TANGARÁ sozinho — e, enquanto você digita, o aviso embaixo já mostra
"✓ Cliente cadastrado · vai gravar como TANGARÁ", em vez do ✓ mudo de antes.
2) O romaneio junta o mesmo cliente. Um botão só, com a carga inteira, tanto no sistema quanto no
app da Expedição — inclusive nas cargas que já estão fechadas com a grafia dividida.
O que NÃO mudou, de propósito: cliente novo com nome parecido continua sendo outro cliente
("TANGARA BEBIDAS" não vira "TANGARÁ"), e onde existem dois cadastros que se parecem o sistema
não escolhe — quem junta cadastro repetido é o 🔗 Juntar repetidos, na tela de Clientes.
Carga que já emitiu os dois papéis não perde nenhum (número
emitido não se apaga nem se muda): ao abrir o romaneio dela, a tela agora avisa que são dois e diz
os números, pra ninguém reimprimir metade da carga achando que é o todo.
🔧 Por dentro: normCliente/mesmoCliente/chaveCargaCliente no
js/54 — a pergunta "é o mesmo cliente?" passou a ter um dono só, e o
js/24, o js/57, o js/58 e o app da Expedição perguntam lá; clienteNomeOficial no
js/01-core. 30 checagens e 6 mutações em
tests/romaneio-cliente-mesmo-nome.test.mjs. Pro Luan: nada.
v2.37.729
🔁 O sistema reprograma SOZINHO quando a chapa acaba — o operador não reprograma mais nada.
Decisão do dono (08/09/2026): "essa confusão se encerra". A régua passa a ser
a CHAPA, não a quantidade do pedido.
Pedido de 10.000, chapa lançada 6.000:
• O operador fecha com 3.000 → ainda tem chapa. Grava no nome dele e o pedido
continua na lista: outro operador pega e continua no MESMO pedido. Não reprograma nada.
• Fechou a chapa (com ±10% de folga, palavra do dono) → a etapa encerra. Como faltam
4.000 e não há mais chapa, o pedido cai em REPROGRAMADO na hora, esperando o PCP
lançar a chapa do resto.
Saíram os dois caminhos de decisão. O "Sair do pedido" do operador
disparava um reprogramar sozinho — mandava o pedido de volta pro PCP como se tivesse faltado
material, com a chapa ainda no chão. E o pedido que fechava abaixo de 95% ficava parado numa
fila até o PCP escolher entre "continuar" e "gerar pedido novo". Os botões
do PCP continuam todos lá: o que saiu foi a espera, não a escolha de ninguém.
A folga da etapa era 2%. Numa chapa de 6.000 isso é 120 caixas — qualquer parada normal
virava "falta produzir". Agora são os 10% que o dono pediu. A folga do pedido
(5%, perda de chapa e apara) não mudou: 4% a menos continua sendo pedido cumprido.
🔍 E a Carteira voltou a explicar o número. Na linha do 23489 POWERDENT TIPO 04 o
dono leu "4.897 pra fazer" com "fez 5.782 + 4.682 = 10.464" logo abaixo, e
nada ligando os dois. O selo que explica isso existe, mas quem procurava o pedido-irmão parava no
primeiro que achasse: a POWERDENT tem dois pedidos de 7.000 da mesma caixa sob o mesmo
número — o código testava o de 13/07, a conta não fechava e ele desistia,
sem nunca testar o de 27/07, que fecha exato (2.103 feitas + 4.897 de saldo = 7.000). Agora varre todos.
Nos pedidos de hoje, 3 linhas a mais passam a mostrar
🔁 reprogramado · fez X · falta Y.
v2.37.728
🚚 App do motorista: a aba "Entregar" mostrava carga que já tinha sido entregue.
Print do dono (08/09/2026), app do Luciano: a carga AOR4231, com os dois pedidos da
Tangara marcados "✅ Entregue às 10:30 — avisado ao escritório",
continuava ocupando a tela de quem ainda tinha entrega pra fazer.
O número da aba já estava certo — a lista é que não. Desde a
v2.37.698 o contador de "🚚 Entregar" conta só carga que não
está toda entregue, mas quem desenha a lista embaixo nunca filtrou nada: o motorista via
3 no botão e 7 cargas na tela. Agora carga 100% entregue sai daqui — ela vive na
aba "✅ Entregues", que tem o histórico inteiro com consulta.
E dentro da carga também separou. Numa carga de 8 paradas com 6 feitas, as 2 que faltavam
ficavam no meio das entregues, na ordem do palete. Agora vem 🚚 FALTA
ENTREGAR em cima com o que resta, e ✅ JÁ ENTREGUES embaixo,
apagadinho. Mesma coisa na viagem da escala, que tinha o mesmo embaralhado.
A parada entregue mantém o número dela (1., 3.…)
mesmo descendo pro grupo de baixo — o número é a ordem da rota, não da lista;
renumerar mentiria sobre o caminho. Pro Luan: nada.
v2.37.727
📱 O ícone da JP só aparecia no iPhone — no Android o app instalava com o desenho genérico do Chrome.
Por que só o iPhone acertava. O iPhone não lê o manifest: ele usa a etiqueta
apple-touch-icon, que aponta pro apple-touch-icon.png — PNG de verdade, 180×180,
branco até os cantos. Está no ar, responde 200, sempre funcionou.
O Android não lê essa etiqueta. Ele tira o ícone da tela inicial do manifest,
e os 14 painéis declaravam ícone só em SVG, colado como data: dentro do
próprio HTML. O Android monta esse ícone como bitmap e não decodifica SVG: ficava sem
ícone nenhum e o Chrome desenhava o dele. Um SVG de 1 KB, nitidez perfeita na aba do computador —
e inútil justamente onde o operador instala.
E tinha um segundo furo junto. O manifest inteiro era um endereço data:, e
caminho relativo dentro de data: não resolve — então o
start_url dos 14 apps nunca valeu. Funcionava por sorte: sem conseguir ler, o Chrome cai na URL
da página, que era a mesma.
O que mudou. Três PNG de verdade (icone-192, icone-512 e
icone-maskable-512), gerados da mesma geometria do favicon.svg — a marca
continua num lugar só; e 19 manifests de verdade (manifest-operador.json,
manifest-expedicao.json…) no lugar do data:. O
maskable vem com folga de propósito: o Android recorta o ícone num círculo de 80%
e comia a moldura da marca.
➕ E mais CINCO telas viraram app. Eram 14 instaláveis; agora são 19.
O próprio sistema (sistema.html) não tinha manifest nenhum — era a
única tela sem — então nunca virou ícone na tela inicial de ninguém; junto
entraram Conciliação, DRE, Ponto e RH (essas quatro ganharam
também o service worker, que só elas não registravam). Estas cinco são tela de
escritório: ficam com a rotação livre, e não travadas em pé como as
14 do chão de fábrica.
⚠ Quem já instalou no Android precisa remover e instalar de novo — o atalho
guarda o ícone de quando foi criado. No iPhone não muda nada.
Pro Luan: nada além do deploy — só arquivo estático
(3 PNG + 19 .json).
v2.37.726
📏 A etiqueta voltou a imprimir as MEDIDAS INTERNAS — e o peso do palete junto.
Print do dono (08/09/2026): etiqueta do 24001 · Tangara · CX 06 AGUA SANITAIRA com
"Cliente.: Tangara" duas vezes — no quadro de cima e no lugar das medidas.
A caixa está cadastrada certinho (330 × 215 × 300 mm, 231,6 g) e o pedido aponta pra
ela: a busca achava. O que faltava era a lista.
No sistema: a etiqueta era o único lugar do sistema que lia o cadastro de caixas direto da
cópia local do navegador — todo o resto (o romaneio inclusive) lê a lista que o
sistema carrega da API. E desde a v2.37.720 a faxina de espaço apaga essa cópia sozinha
quando o navegador passa de 80% do limite (é a maior de todas, ~1 MB): tudo continuava funcionando e
só a etiqueta emudecia. Navegador cheio recusando gravar dava no mesmo desde sempre.
No tablet do operador: a cópia de reserva era lida errado (desembrulhada pela metade), então
etiqueta impressa antes do primeiro sincronismo saía sem medida e sem peso. Consertado também.
⚠ E quando a medida não estiver cadastrada mesmo, a etiqueta AVISA. Antes ela
repetia o nome do cliente naquele quadro — que já sai grande em cima e no rodapé —
e ninguém descobria que o que faltava era a medida. Agora sai NÃO
CADASTRADA em vermelho, embaixo de "Medidas internas.: C L A": quem imprime vê e manda
cadastrar. O aviso de "⚠ NÃO CONFERIDA" (medida que veio de cadastro repetido)
continua igual, no mesmo lugar.
Teste novo: tests/etiqueta-medida-sem-cache.test.mjs
(18 checagens + 3 mutações), com o caso real da Tangara. Pro Luan: nada.
v2.37.725
📡 O sensor pronto pra TODAS as máquinas — e a Corte e Vinco conta em chapas × poses.
Pedido do dono (08/09/2026): "quero o mesmo na Coladeira quando instalar o sensor, na Corte e Vinco,
na Grampeadeira e em todas as máquinas cadastradas — não podemos esquecer disso".
Coladeira, Grampeadeira e máquinas cadastradas: já funcionam do mesmo jeito da Slotter. Basta o
ESP32 mandar com a chave da máquina (está na ficha do ESP32: coladeira,
grampeadeira, corte_vinco, ou a chave do cadastro) e ligar os dois botões no
cartão dela no Mural.
Corte e Vinco: o sensor vê chapas, e cada chapa vira N caixas (as poses da faca). Até aqui o
app leria 40 chapas como 40 caixas num pedido de 160. Agora o número do sensor é multiplicado pelas poses
do pedido — no campo do tablet (que é em chapas), no parcial, na barra e no ritmo do Mural, na sugestão
de liberar e no fim de turno. Quando a Corte e Vinco é a última da rota (paletiza), conta caixa, como o
apontamento já fazia. As réguas do automático (20 caixas em 2 min, 60 s parado, 20 pra retomar) continuam
contando o que passa na frente do sensor.
Slotter, Coladeira e Grampeadeira não mudam nada (poses = 1).
v2.37.724
📡 O número do sensor vai onde o operador digita: liberar pra próxima etapa, finalizar e fim de turno.
Pedido do dono (08/09/2026): "quero que a marcação do sensor suba no total onde o operador digita para
liberar para a próxima etapa" — o Miller olhava o sensor e digitava 1.500 na mão. Com o
🤖 O APP AGE SOZINHO ligado na máquina:
• 📤 Liberar parcial p/ próxima etapa: a pergunta já vem com o que o sensor contou desde a última
liberação (no corte e vinco, em chapas). O operador confere e corrige; nada é liberado sozinho.
• Finalizar e fim de turno: o campo já vinha do sensor (v668); agora a tela diz que o número
veio de lá, pra conferir.
Corrigir na mão deixou de desligar o sensor. Na v668, digitar no campo parava o preenchimento
daquele pedido e o número congelava com a máquina rodando. Agora a correção vira um ajuste
(o que você digitou menos o que o sensor dizia) e o sensor segue contando por cima. Apagar o campo
volta ao sensor. O ajuste fica gravado no pedido e sobrevive a recarregar.
Com o 🤖 desligado, nada disso aparece: tudo como era. Sem sinal do
aparelho, nenhuma sugestão.
v2.37.723
🟢 Mural: a cor do cartão segue o mesmo ritmo que a linha mostra.
Na Slotter (Miller, 08/09/2026) a linha dizia 5.107 cx/h · meta 4.703 e o cartão estava
AMARELO, "abaixo da meta". A linha lia o sensor; a cor ainda lia o apontamento (1.500 cx em
26 min), que chega atrasado e é outra medida. Dois relógios na mesma tela.
Agora, na máquina que está 📡 MOSTRANDO PELO SENSOR, a cor usa o ritmo do sensor — a mesma
conta da linha. Acima de 85% da meta, verde; abaixo, amarelo com "abaixo da meta".
Sem sensor, sem sinal, com a janela do sensor ainda curta ou lendo
pelo apontamento, continua exatamente como era.
v2.37.722
📡 Quando o sensor faz o pedido entrar em produção, as caixas que dispararam contam no pedido.
Pedido do dono (08/09/2026): "pode contar as 21 caixas do ajuste no pedido também". Até
aqui o contador do pedido começava no instante em que o app percebia a produção — e as 21 caixas
que fizeram ele perceber ficavam de fora. Agora o zero é o começo da rajada (o que passou
nos últimos 2 minutos): o pedido já nasce com essas caixas.
O que passou antes disso, minutos atrás no ajuste (chapa de teste), continua fora: é ajuste,
não produção. E quando o operador aperta o ▶ na mão, o contador começa no ▶, como está.
O ▶ pode ser do operador ou do automático — o automático é a rede
para quando ele esquece de apertar.
v2.37.721
🚨 O 🤖 do Mural NUNCA chegava no tablet — o app do operador não via o botão ligado.
Achado hoje (08/09/2026) com o Miller na Slotter: o botão 🤖 O APP AGE SOZINHO estava
LIGADO no Mural e mesmo assim 347 caixas passaram "em ajuste" sem o pedido entrar em
produção. Motivo: o Mural grava a configuração da máquina por um nome interno
("impressora") e o tablet perguntava por outro ("Máq. B Slotter"). O tablet nunca achava a
configuração e trabalhava como se tudo estivesse desligado — desde a v2.37.641 (02/09).
Nenhuma ação automática do sensor funcionou até hoje: nem entrar em produção, nem pedir motivo
de parada, nem retomar, nem preencher a quantidade (v668).
Agora os dois falam da mesma máquina: o app acha a configuração pelo nome, pela chave ou
pelo de-para das 4 máquinas de fábrica, e a configuração passa a guardar o nome da máquina
(é o que faz máquina cadastrada casar também).
Nada muda no que já estava gravado. Na Slotter, com o 🤖 ligado
como está, o próximo pedido que passar de 20 caixas em 2 minutos no ajuste entra em produção
sozinho. As 347 caixas de hoje ficaram fora da contagem do pedido do Miller: o ▶ foi na mão às
07:36 e o contador começou ali — corrija a quantidade no tablet, como sempre.
v2.37.720
🧹 O sistema libera espaço sozinho quando o navegador aperta. Pedido do dono em 01/09 ("faz o sistema liberar espaço sozinho quando apertar"), depois da v2.37.633. Foi feito naquele dia como "634" e ficou sem commit numa worktree; subiu agora, conferido contra a base de hoje.
🔍 Por que enchia: o sistema e os ±20 painéis moram no mesmo endereço e dividem os mesmos ~5 MB que o navegador dá pro site. São mais de 200 cópias guardadas, e só a de pedidos passa de 890 KB. Nunca existiu faxina.
✅ Agora: quando aperta, descarta sozinho as cópias que o servidor reescreve no próximo carregamento (pedidos, caixas, clientes, cadastros) e continua trabalhando, avisando quanto liberou. Em dois momentos: na abertura, se já passou de 80% do limite, e na hora, se uma gravação for recusada (tenta gravar de novo uma vez). O link "liberar espaço" da tela de login passou a usar essa mesma faxina segura em vez da limpeza de troca de usuário, que levava as filas junto.
🔒 O que ele NUNCA apaga: nada que esteja esperando pra subir pro servidor — apontamento do operador, parada em reenvio, carga em montagem, ocorrência, aviso do motorista, recebimento do vendedor. Se há edição de pedido que o servidor ainda não confirmou, nem a cópia de pedidos ele encosta. Chave que ele não reconhece fica onde está: o padrão é manter.
🔧 Por dentro: js/91-espaco-livre.js (jpLiberarEspaco, jpFolgarSePrecisar, JP_FILAS_INTOCAVEIS); todo cadastro do setupCadastroApi (js/02) se declara descartável sozinho; gatilho reativo no jpGravarLocal; link do login no js/07. 30 checagens + mutação em tests/espaco-livre-sozinho.test.mjs. Pro Luan: nada.
v2.37.719
🏦 A página antiga de conciliação parou de gravar no sistema — último item da Onda 0 (achado C-4). O painel_conciliacao.html abre sem login, na internet, e salvava o Contas a Receber inteiro de uma vez. Bastava alguém abrir com uma cópia antiga na tela pra apagar as baixas de todo mundo — é o mesmo mecanismo que engoliu 6 romaneios em agosto.
⛔ Agora ela abre com um aviso vermelho no topo ("desativada — use Contas & Previsão") e não escreve mais nada. Ainda dá pra abrir um extrato e conferir na tela; nada disso chega ao sistema. O arquivo não foi apagado (REGRA ZERO).
🔒 Segunda tranca, precisa do Luan: a regra que tira a página do ar entrou no docs/nginx-bloqueio-arquivos-internos.conf — aquele arquivo de bloqueios que está esperando ele desde 26/07. A regra usa o nome exato da página, de propósito: um curinga derrubaria o operador e a expedição junto.
👉 A conciliação de verdade continua onde já estava: aba 💵 Contas & Previsão, dentro do sistema, com login.
🔧 Por dentro: aviso no topo do painel_conciliacao.html, salvarContas/salvarExtrato sem PUT, location = /cartonagem2/painel_conciliacao.html { return 404; }. 22 checagens e 4 mutações em tests/painel-conciliacao-desativado.test.mjs.
v2.37.718
🧾 A nota de papel entrava pela metade — e o crédito de imposto sumia — sexto item da auditoria (E-3). Quando o banco do servidor estava desatualizado, importar o XML gravava só o cabeçalho: sem os itens, sem os impostos e sem guardar o XML. Em silêncio, com a tela dizendo "importado".
💸 O estrago: o crédito de ICMS e IPI daquela entrada desaparecia do sistema; a nota ficava marcada como já importada, então reimportar depois dava "nota duplicada" — não havia segunda chance; e o XML, que é obrigação guardar por 5 anos, não era guardado.
🚪 Agora ela recusa e explica: "peça ao Luan a atualização 040" — e nada é gravado. É o que a nota de insumo (tinta, cola, faca) já fazia certo desde que nasceu.
♻️ E tem conserto pro que já passou: botão novo Reprocessar itens — pega o XML guardado da nota e cria os itens que faltaram. Roda quantas vezes quiser: na segunda ele não cria nada e nunca apaga nem substitui item existente. Nota antiga que não tem o XML guardado avisa pra reimportar o arquivo (a importação reconhece a duplicata e não soma estoque de novo).
🔁 De quebra: três funções que estavam escritas duas vezes (uma no papel, outra no insumo) e já tinham se separado — a do insumo transformava data com espaço em vazio — viraram uma só. E o servidor passou a ler a nota com a mesma régua da tela, aquela que sabe que o imposto do IPI não pode vazar pro campo do ICMS.
🔧 Por dentro: api/src/lib/nf-entrada.js (novo: ajudantes, leitor de XML no servidor reaproveitando o js/65-nfe-entrada.js, inserirItensDaNf, reprocessarItensDaNf); POST /api/papel/nfs/:id/reprocessar-itens. 51 checagens e 5 mutações em tests/papel-entrada-fail-closed.test.mjs; um teste antigo que exigia o comportamento errado foi corrigido e a razão ficou escrita nele. Precisa do Luan: pm2 restart all.
v2.37.717
🗂️ Qual cadastro fiscal do produto vale AGORA — quinto item da auditoria (F-12). O cadastro fiscal da caixa é um histórico: cada vez que se salva, nasce uma linha nova (é de propósito — assim dá pra ver o que estava cadastrado no dia de cada nota). Só que todas ficavam valendo ao mesmo tempo, e o sistema escolhia "a mais recente" em cinco lugares diferentes, cada um com a sua regra escrita à mão.
🎲 O risco: quando duas linhas nascem com o mesmo horário, o banco devolve qualquer uma delas — e pode devolver uma hoje e outra amanhã. Traduzindo: a nota podia sair com um NCM ou um IPI que ninguém cadastrou por último.
✅ Agora: a regra mora num arquivo só, com desempate que nunca sorteia; e ao salvar um cadastro novo, o anterior da mesma família é aposentado (marcado como inativo — a linha nunca é apagada, e as notas antigas continuam apontando pro cadastro com que foram feitas). O padrão da caixa não encosta no padrão da chapa: são famílias diferentes.
🔎 Conferido antes de mexer: o empate que a auditoria temia não está acontecendo hoje (cada atualização do banco roda separada, e a 042 usa nomes diferentes pra caixa e chapa). O que estava vivo mesmo era o acúmulo de cadastros ativos.
🔧 Por dentro: api/src/lib/fiscal-perfil.js (novo) com ORDEM_PERFIL_VIGENTE e as duas consultas; as 5 leituras de nfe-pre-nota.js e routes/fiscal.js passaram a usá-las; o /produto/sync grava e aposenta na mesma transação. 31 checagens e 4 mutações em tests/fiscal-perfil-vigente.test.mjs (a metade que precisa de Postgres se pula sem Docker). Precisa do Luan: pm2 restart all.
v2.37.716
🔐 O cadastro fiscal estava aberto a qualquer aparelho da fábrica — o achado mais grave da auditoria em segurança (S-1). As rotas de /api/fiscal não pediam login nem permissão: nenhuma. A única barreira era a senha de acesso da API, que é a mesma em todos os aparelhos e vai pra todo navegador que abre o sistema. Na prática, do tablet do operador dava pra trocar o CNPJ e o regime da empresa que fatura, virar o ambiente de teste para PRODUÇÃO, mexer na série e no número da próxima nota, e alterar NCM e alíquota de qualquer produto — sem ficar registrado quem fez.
🔒 Agora: ler continua igual pra todo mundo (nenhuma tela quebra). Gravar exige a permissão nova 🧾 Cadastro fiscal — que nasce para o Admin e o Financeiro. Enquanto o Luan não roda a atualização do banco, a API exige Admin: a porta fecha no reinício, em qualquer ordem.
🚫 CNPJ, regime (CRT) e UF de empresa que já tem nota autorizada não mudam mais — a nota velha continuaria com o valor antigo e o cadastro passaria a descrever outra empresa. Quem errou resolve com o contador: cadastra a certa e desativa a errada (nada se apaga). Mudar telefone, endereço ou razão social continua liberado.
✍️ A pré-nota parou de aceitar autor digitado. Sem login ela era criada em nome de quem a requisição dissesse que era. Agora o nome sai do crachá, e toda criação grava um evento no livro da nota (antes só o cancelamento gravava).
🔧 Por dentro: api/src/lib/fiscal-guarda.js (régua pura: escrita nova nasce fechada; /simular segue aberto porque só calcula), router.use(carregarSessao) + trava em routes/fiscal.js, autorDaRequisicao em routes/nfe.js, evento emissao_teste em nfe-pre-nota.js. 47 checagens e 5 mutações em tests/fiscal-escrita-so-com-permissao.test.mjs.
⚠️ Precisa do Luan: npm run db:migrate (migration 046) + pm2 restart all.
v2.37.715
🧾 A pré-nota nunca mais fica presa em "Calculando…" — terceiro item da auditoria fiscal (achado F-11). O erro de uma palavra que travava a tela já tinha sido consertado na v2.37.690 (conferi linha por linha antes de mexer). O que continuava aberto era o buraco que fez esse erro doer: os dois botões de gravar da pré-nota não tinham rede embaixo. Qualquer tropeço antes de abrir a transação saía sem resposta nenhuma — a tela girava pra sempre e o servidor colecionava erro solto.
🕳️ E o teste que existia não olhava nada: ele procurava palavras no código-fonte, e o código com o defeito passava. Agora existe um teste que roda a pré-nota contra um banco de mentira sem a atualização 043 e confere que ela responde "peça a migration 043" (503) em vez de travar — e que quem não usou o campo continua emitindo normal.
🔧 Por dentro: try/catch nos dois router.post de api/src/routes/nfe.js (os GET já tinham). 15 checagens e 3 mutações em tests/pre-nota-sem-migration-043.test.mjs. Precisa do Luan: pm2 restart all (é rota da API) — mas só quando o pacote da Onda 0 for subir.
v2.37.714
🧾 IPI suspenso: o imposto sumia da nota, mas continuava engordando o ICMS — segundo conserto da auditoria fiscal (achado F-5). Quase metade das caixas da JP sai com IPI suspenso (311 de 653 itens em 2026, medido no Sectra). O sistema zerava o IPI depois de fazer as contas: o número aparecia zero na tela, mas o ICMS, o PIS e a COFINS já tinham sido calculados com ele dentro.
💰 O tamanho do erro: R$ 10.000 pra Minas, consumidor final, IPI 15% suspenso — a base do ICMS ficava em R$ 11.500 em vez de R$ 10.000, e o ICMS saía R$ 1.380 onde o certo é R$ 1.200. R$ 180 de imposto inventado em cada R$ 10 mil.
🔧 Por dentro: o aplicarIpiSuspenso (fiscal-operacao.js) passou a receber a entrada do cálculo e refazer a conta com a alíquota zerada — o mesmo caminho que a industrialização já usava —, carimbando depois o CST 55 e o texto legal ("Saída com suspensão do IPI, art. 29 da Lei 10.637/2002 — RIPI art. 415"). Quem chamar do jeito antigo agora leva erro na cara em vez de devolver número errado calado. 22 checagens e 4 mutações em tests/fiscal-ipi-suspenso-base.test.mjs. Sem servidor, sem Luan.
v2.37.713
🧾 O total da nota estava cobrando o DIFAL do cliente — primeiro conserto da auditoria fiscal de 08/09/2026 (achado F-4). Quando a venda é pra fora de São Paulo e pra quem não é contribuinte (consumidor final), a JP recolhe por fora um imposto chamado DIFAL. Esse valor tem que aparecer na nota como informação — mas não pode entrar na soma. O sistema somava.
💰 O tamanho do erro: uma venda de R$ 10.000 pra Minas Gerais, com IPI de 15%, fechava R$ 12.341,46. O certo é R$ 11.500,00 (os produtos mais o IPI). Fora o dinheiro cobrado a mais, a nota seria recusada pela SEFAZ (rejeição 610, "total não confere").
🔁 De quebra: o total da nota era calculado em dois lugares diferentes, cada um do seu jeito. Agora é um só.
🔧 Por dentro: nova totalNota() em api/src/lib/fiscal-calc.js; o aplicarIpiSuspenso do fiscal-operacao.js perdeu a conta própria e chama ela. O DIFAL e o FCP continuam calculados e informados (viram vICMSUFDest/vFCPUFDest). 21 checagens e 4 mutações em tests/fiscal-total-da-nota.test.mjs; os 17 testes do motor conferidos contra XML real passaram sem mudar um centavo. Sem servidor, sem Luan (a nota oficial ainda sai pelo Sectra — isto é o motor que vai emitir).
v2.37.712
🔒 No item do orçamento, o campo "Fechamento da caixa nova" some quando a rota está escolhida — e a rota manda no fechamento. Pedido do dono: "esconde o fechamento quando tiver rota". A rota já é a resposta (Coladeira = cola, Grampeadeira = grampo, "sai pronta" = sem); dois campos era convidar contradição. No lugar do campo aparece uma linha dizendo o que a rota decidiu; tirou a rota, o campo volta. Caixa cadastrada continua sem o campo.
🐛 A brecha que apareceu ao fazer: a rota já mandava nas máquinas e no pedido, mas o grampo e a cola do custo (o requer do js/71) liam o campo de fechamento — rota "→ Grampeadeira" com o campo vazio orçava sem arame. Agora o acabamento da rota vira o fechamento do cálculo (também sobre caixa cadastrada com fechamento diferente, igual às máquinas) e é ele que o item grava.
🔧 Por dentro: orcRotaAcab, orcFechamentoDaTela, orcFvBoxMostrar/Sinc (js/08) — um dono só pro display da caixinha; ctx.fechamento e a caixa dos insumos obedecem ctx.rota no orcCtxDoItem. 20 checagens e 4 mutações em tests/fechamento-pela-rota.test.mjs. Sem servidor, sem Luan. (Era pra ser a 710; a main ganhou 710 e 711 no caminho — e o selo ATUAL, parado na 709, voltou pro topo.)
v2.37.711
🌳 FSC: a lista de notas de papel (/api/papel/nfs) passou a devolver o CNPJ do fornecedor. É por ele que a regra R1 casa a nota com o cadastro do fornecedor — sem ver o número não dava pra conferir por que uma entrada ficou "Não FSC". Só leitura, nada muda na importação.
⚠️ Precisa do Luan: pm2 restart all (é rota da API).
v2.37.710
🗓️ O relatório do papel de terceiro agora sai por DIA, SEMANA ou MÊS.
Era um pedido do começo que nunca tinha sido feito. Quando o controle do papel da DCX
foi desenhado, o pedido era "relatório semanal ou diário" — e só existia semanal.
Agora tem três botões no topo da tela: Dia · Semana · Mês. As setas ◀ ▶ andam no
período escolhido, e o "Hoje" volta pro atual.
Muda o recorte, não a conta. Saldo, consumo por produção, cargas e entradas são os
mesmos de sempre — só olhando a janela que você escolheu. O relatório impresso acompanha:
sai DIÁRIO, SEMANAL ou MENSAL no cabeçalho, com o período certo, e cada
um ganha o seu próprio número oficial (imprimir o mesmo dia de novo devolve o mesmo número,
como já era com a semana).
📨 E o envio automático também. Na ficha do terceiro (Cadastros ▸ 🏭 Terceiros)
tem um campo novo: de quanto em quanto tempo — toda semana (o de sempre) ou todo dia.
É por cliente: um pode receber diário numa semana cheia e outro seguir no semanal. Quem já
recebe não muda: ficha sem o campo continua semanal.
Dois cuidados que ficaram no código: o relatório sempre
cobre o período que já fechou (o diário manda o dia anterior — mandar o dia em
andamento seria mandar número errado); e o quadro "quais semanas ficaram sem relatório"
passou a contar só os semanais, senão um relatório diário de uma terça seria lido
como início de semana e a conta apontaria buraco onde não tem.
v2.37.709
🐛 📄 Papel de Terceiro travava na DCX PACKAGING — ficava em "⏳ Buscando o papel de terceiro…" pra sempre. Achado em 07/09/2026 gerando o relatório de uso da DCX.
🔍 O que era: o bloco I · Acerto do saldo (livro × rolos do pátio) usava um formatador que só existe dentro da impressão. Na tela ele não existia, e o desenho estourava. Como esse bloco só aparece quando há diferença, o dono com diferença era justamente o que travava — a DCX está com 5.698 kg de diferença entre livro e rolos (miolo 140 g: 3.942 kg · top liner 180 g: 1.756 kg). Os outros donos abriam normal.
✅ Agora: a tela abre pra qualquer dono, com ou sem diferença. A impressão não mudou.
🔧 Por dentro: kgf do bloco I no renderPapelTerceiro (js/75) passou a usar o ptFmtN de módulo em vez do num local do ptImprimir. 3 checagens e 1 mutação em tests/papel-terceiro-tela-dcx.test.mjs. Sem servidor, sem Luan.
v2.37.708
🐛 O arame não entrava no pré-cálculo — e a conta pela altura da caixa não acontecia. Você mostrou: o arame na lista de acessórios do item, e no 🧮 Pré-cálculo só a alça; e o grampo sem olhar a altura da caixa.
🔍 Era UMA causa só: a altura da caixa nunca chegava ao motor dos insumos. Das cinco chamadas que montam o cálculo do item, nenhuma passava a altura — e é dela que sai a conta do grampo (um a cada N mm do corpo). Sem altura, o motor devolvia "falta a altura da caixa" e o arame sumia do preço calado. A altura estava na tela o tempo todo; o recorte que ia pra conta é que era magro.
✅ Agora: a altura (e a aba de fechamento, como reserva) vai junto pra conta. Na caixa de 660 mm da sua tela: 9 grampos (660 ÷ 80, arredondado pra cima) × R$ 0,03 = R$ 0,27/cx; numa caixa de 200 mm, 3 grampos. O arame entra no 📋 Custo completo, na memória e no pré-cálculo do gestor.
🏷️ E a etiqueta parou de enganar: na lista de acessórios do item, o arame dizia "10 un/cx" (o consumo velho do cadastro, que o motor nem lê). Agora diz "pela altura da caixa (1 a cada 80 mm, mín. 2)" e não mostra campo de quantidade — a quantidade é calculada, não digitada. Fita pela volta da caixa, idem.
🔧 Por dentro: `A` e `alturaAbaMm` no ctx dos insumos dentro do orcCtxDoItem (js/08, lendo #orc-it-a quando quem chama não passa); ctxDoOrcamento (js/71) aceita a aba dita por quem chama; chip do orcInsumosRender. 32 checagens e 9 mutações em tests/insumo-da-caixa-alca.test.mjs. Sem servidor, sem Luan.
v2.37.707
💠 O R$/kg ficou ao lado do preço da caixa. Você pediu: "quero o valor do kilo perto do valor da caixa pra ficar fácil visualizar".
✅ Onde: na caixa azul do Preço da caixa (R$/un), agora tem o R$/kg do lado direito. Dá pra digitar nos dois: mexeu no preço, o R$/kg se ajusta; mexeu no R$/kg, o preço se ajusta. É o mesmo par que já existia desde a v2.37.146 — só que agora um está do lado do outro.
📊 Embaixo do R$/kg aparece a comparação que se faz de cabeça: "▼ 41,7% abaixo do nominal (R$ 9,400/kg) · 2,041 kg/cx". É o nominal da chapa escolhida e o peso da caixa — os dois números que ligam o R$/kg ao R$/caixa.
🔒 O número tem um dono só: o campo R$/kg de cima (junto da chapa) continua mandando; o de baixo é espelho e chama a MESMA função de sempre. Nada de duas contas pro mesmo valor. E enquanto você digita no campo novo, o recálculo não reescreve por cima.
🔧 Por dentro: orcRskgDoLado + orcRskgLadoTela (js/08), campo orc-r-rskg no sistema.html. 14 checagens e 4 mutações em tests/rskg-do-lado-do-preco.test.mjs. Sem servidor, sem Luan.
v2.37.706
🔄 O almoxarifado ficava PARADO na primeira leitura do sistema — o arame cadastrado lá não aparecia aqui. Você mostrou: ARAME MIRUNA cadastrado no app do Almoxarifado (R$ 27/kg, 1 emb. = 25 kg) e a lista de insumos do orçamento sem ele.
🔍 O que era: o sistema lia o estoque uma vez por sessão e guardava. Item novo, preço novo ou saldo novo só apareciam depois de F5. Não era lentidão da rede: era leitura que nunca se repetia.
✅ Agora: a leitura vale 1 minuto. A aba 🧰 Insumos do Orçamento e a lista de acessórios do item pedem o estoque de novo e se redesenham sozinhas quando ele chega. No topo da aba aparece de quando é o que está na tela ("lido há 12 s") e um botão ↻ Puxar do almoxarifado agora pra não esperar nem isso.
📌 Sobre o resto do sistema: cadastros e telas normais já conversam a cada 8 segundos entre os apps — ali não havia atraso. O que estava parado era só o estoque do almoxarifado dentro do sistema, por causa dessa leitura única.
🔧 Por dentro: jpAlmoxGarantir (js/31) ganhou validade de 60 s + jpAlmoxAtualizadoEm; renderCcInsumos (js/13) e orcInsumosRender (js/08) repuxam e redesenham; ccInsumosRecarregar é o ↻. Continua leitura pura — quem grava no doc é o app do almoxarifado. 40 checagens e 8 mutações em tests/preco-insumo-da-compra.test.mjs. Sem servidor, sem Luan.
v2.37.705
🐛 "Acessórios e serviços desta caixa" aparecia VAZIO. Você mostrou a tela orçando a teste 01 (caixa nova da ALPACK): o campo estava lá, mas sem opção nenhuma pra escolher.
🔍 O que era: a lista só era montada no caminho da caixa cadastrada — e é justamente na caixa nova que você precisa escolher a alça ou o serviço externo na mão. Quem orçava caixa nova via um campo mudo.
✅ Agora: a lista é montada ao abrir o orçamento e também quando a referência não casa com caixa cadastrada. Aparecem os cinco insumos com base: 🧰 Arame miruna · 🧰 Paletes · 🧰 Cola · 🧰 Alça · 🤝 Colagens externa. Caixa nova começa com a lista vazia, mas com as opções pra escolher; caixa cadastrada continua trazendo os acessórios dela.
🔧 Por dentro: orcInsumosSet([]) no abrirModalOrcamento e no ramo "caixa não casou" do orcPreencherDaCaixa. 27 checagens e 7 mutações em tests/insumo-da-caixa-alca.test.mjs, com mutação nova que acusa a volta do campo vazio. Sem servidor, sem Luan.
v2.37.704
🖨️ O 📊 Pós-cálculo agora sai em papel / PDF. Você pediu: "quero ver isso em PDF no pós-cálculo".
✅ Onde: 💰 Financeiro ▸ 📊 Pós-cálculo ▸ botão 🖨️ Imprimir / PDF, no canto de cima. Abre a janela de impressão em A4 retrato — dá pra escolher "Salvar como PDF".
📋 O que sai: o resumo de todos os pedidos (faturou, custo orçado, custo real, sobrou, margem contra a prevista) e, pedido a pedido, máquina por máquina: hora orçada × hora apontada, o R$ de cada uma, quantos registros, ajuste + produção e a parada que ficou dentro. Fecha com o lembrete de medido × herdado — só a máquina tem apontamento por pedido; papel, tinta, insumos e frete vêm do orçamento.
🔒 Documento interno: tarja vermelha no topo e no pé, e só imprime quem já podia ver a tela (a mesma trava do DRE). Tem custo, hora de máquina e margem — não vai pro cliente.
🔧 Por dentro: pcDocHTML/pcDocCSS/ccPosCalcImprimir no js/77, lendo o mesmo resultado do doPedido que a tela desenha (uma conta só, §9.13); papel pelo js/68. Sem servidor, sem Luan.
v2.37.703
📦 "Puxar do almoxarifado": o insumo nasce já ligado ao item do estoque, num passo só. Você pediu depois de cadastrar os itens lá: "e depois puxar dentro dos insumos".
✅ Onde: 💰 Financeiro ▸ 🧰 Insumos do Orçamento ▸ na caixa de cadastrar, escolha o item na lista e clique em 📦 Puxar do almoxarifado. O insumo nasce com o nome e a unidade do item, já ligado — o preço vem do estoque desde o primeiro dia, sem digitar número nenhum. Em seguida o ⚙ abre pra você dizer de que a caixa depende (por caixa, por pallet, por amarrado…) e quanto gasta.
🔒 Duas travas: item já ligado a um insumo não aparece na lista pra puxar — dois insumos no mesmo item seriam o mesmo custo cobrado duas vezes. E o insumo nasce sem base: enquanto você não disser de que ele depende, ele não entra em preço nenhum.
🔧 Por dentro: ccInsumoPuxarAlmox (js/13) cria com almoxId + unidade do item e abre o ccInsumoOrc. 33 checagens e 7 mutações em tests/preco-insumo-da-compra.test.mjs. Sem servidor, sem Luan.
v2.37.702
💸 Comprou mais caro → o orçamento novo já sai com o preço novo, e os que estão na rua AVISAM. Você pediu: "hoje o preço foi feito com o arame a R$ 25 o quilo e amanhã vai pra R$ 30; quando entregar a compra, aviso que tem mudança, e já começa a valer" — e "tudo que está no insumo vem do estoque do almoxarifado da Cartonagem, e os preços também".
📦 O preço passou a morar num lugar só: o almoxarifado. No ⚙ do insumo (🧰 Insumos do Orçamento) escolha o item do almoxarifado de onde vem o preço. O R$/kg deixa de ser digitado e é lido do estoque na hora — não existe cópia pra ficar velha. Só falta dizer quanto pesa 1 unidade (um grampo, uma alça) pra virar preço por unidade.
🛒 Na baixa da compra (🖨️ Lançamentos ▸ ✅ Dar baixa ▸ Lançar), o preço que veio na nota atualiza o item no almoxarifado sozinho, com histórico de quem mudou, quando e de quanto pra quanto. ⚠️ Só quando a unidade da compra é a mesma do estoque: comprou uma caixa com 5.000 grampos? O preço da caixa não é o preço do quilo — aí o sistema não mexe e avisa.
⚠️ O aviso: logo depois da baixa abre uma tela dizendo o que mudou e quais orçamentos ainda abertos foram feitos com o preço velho, com a diferença em reais de cada um. O cartão de cada orçamento fica marcado com 💸 preço de insumo mudou. Eles não se reescrevem sozinhos — preço que já foi pro cliente é negociado; pra refazer, abra o orçamento e salve o item de novo. Convertido e reprovado ficam de fora.
🔧 Por dentro: jpAlmoxPreco (js/31, read-modify-write + historicoPreco); ccInsumos() (js/13) virou a porta única que resolve o preço do item ligado (almoxId); _ccPrecoDaCompra no fim do ccCestaLancar; jpOrcPrecoInsumoImpacto + jpOrcAvisarPrecoInsumo (js/08) comparam o preço gravado na memória do item com o de hoje. 27 checagens e 6 mutações em tests/preco-insumo-da-compra.test.mjs. Sem servidor, sem Luan.
v2.37.701
⚖️ Insumo comprado por QUILO: agora é só dizer o preço do quilo e o peso da unidade. Você disse: "o arame é por kilo, eu vou pesar um grampo e ver quanto pesa e colocar no cadastro".
✅ Onde: 💰 Financeiro ▸ 🧰 Insumos do Orçamento ▸ ⚙ do insumo ▸ bloco ⚖️ Comprado por QUILO?. Preencha preço do quilo (R$/kg) e peso de 1 unidade (g) — o sistema mostra na hora o preço por unidade e é ele que entra no custo: R$/kg × peso ÷ 1.000. Ex.: arame a R$ 25,00/kg com grampo de 1,2 g = R$ 0,03 por grampo.
🔒 Um número só manda: com os dois preenchidos, o campo "preço por unidade" fica só de leitura — não existem dois donos do mesmo valor. Preenchendo só um dos dois, a tela avisa o que falta e continua valendo o preço por unidade digitado. Deixando os dois em branco, nada muda.
📋 Fica registrado de onde veio: a lista mostra "R$ 0,0300/un · ⚖️ R$ 25,00/kg × 1,2 g". Quando o arame subir de preço, você mexe só no quilo e todo orçamento novo já sai com o valor certo. Serve pra qualquer insumo comprado a peso — arame, cola, fita.
🔧 Por dentro: `precoKg` e `pesoUnG` no insumo (jsonb, sem migration); o `preco` por unidade é derivado deles no salvar do ⚙ (js/13), então o motor de custo (js/71) continua lendo um campo só. 31 checagens e 7 mutações em tests/insumos-orcamento-tela.test.mjs. Sem servidor, sem Luan.
v2.37.700
📌 O grampo passa a contar pelo CORPO da caixa (a altura), não pela aba de fechamento. Você disse: "tem que ser pelo corpo da caixa, pela altura; ex.: a caixa é 660 ÷ 11 dá 60 mm entre grampos".
🔍 O que era: a conta procurava primeiro o lap (aba de fechamento) do cadastro da caixa e só usava a altura quando o lap estava vazio. Aba tem uns 35 mm, então toda caixa com lap cadastrado caía no mínimo — uma caixa de 660 mm pagava 2 grampos em vez de 11.
✅ Agora: grampos = altura da caixa ÷ o passo, arredondado pra cima, nunca menos que o mínimo, vezes o número de abas. Sem altura cadastrada, o lap ainda entra como reserva — o custo não some. Caixa de 660 mm: com passo 60 dá 11 grampos (60 mm entre eles), com passo 80 dá 9.
⚙️ Onde se define: 💰 Financeiro ▸ 🧰 Insumos do Orçamento ▸ botão ⚙ do arame: passo (um grampo a cada N mm), mínimo por aba e abas por caixa. O texto da tela foi reescrito pra dizer a conta com todas as letras.
🔧 Por dentro: grampos() no js/71 passou a ler alturaCaixaMm primeiro e alturaAbaMm como reserva. 37 checagens em tests/insumos-orcamento.test.mjs, com mutação nova que acusa a volta da regra antiga. Sem servidor, sem Luan.
v2.37.699
🔢 "0,00 un × R$ 15,00" no custo dos insumos — número zero mentindo num documento de custo. Apareceu enquanto conferíamos por que o item de 50 mil saiu mais caro que o de 10 mil.
🔍 O que era: a linha do insumo no 📋 Custo completo (e no 🧮 Pré-cálculo do gestor) lia um campo que nunca existiu na conta do motor. Resultado: todo insumo aparecia com "0,00" de consumo, mesmo cobrando certo. O valor sempre esteve certo — só a explicação ao lado estava zerada.
✅ Agora: "Paletes 1,00 un por pallet × R$ 15,00", "Arame 3 por caixa × R$ 0,03" — o mesmo texto que o motor já montava e ninguém via.
📊 Da conferência do orçamento 0037 (fica registrado): o item de 50 mil ficou mais caro por caixa só por causa do papel — 0,092 kg/cx contra 0,038 kg/cx do outro item, 2,42× mais chapa na mesma caixa de 150×100×70 mm. Tudo que depende da quantidade ficou mais barato no de 50 mil, como tem que ser: máquina R$ 0,0993/cx contra R$ 0,1109/cx, e clichê/faca R$ 0,0081/cx contra R$ 0,0406/cx se estivesse em 10 mil. Confira as medidas da chapa e as poses do item de corte e vinco.
🔧 Por dentro: _linhasCustoCompleto (js/72) usava l.qtdInsumo; os campos reais da linha do js/71 são detalhe, consumo, nBases e total. Sem servidor, sem Luan.
v2.37.698
🚗📜 App do motorista: a mesma consulta, só com as cargas dele. Você pediu: "a mesma consulta no app do motorista, mas somente a carga dele, de cada um".
✅ Onde: na aba ✅ Entregues, que é o histórico dele. Ganhou Um dia · Período · Tudo e filtros por caminhão e cliente. Filtro de motorista não existe lá — seria um filtro de um valor só.
📅 A aba deixou de mostrar só os últimos 7 dias: agora é tudo que ele já levou, com data, e uma linha diz o recorte (quantas cargas suas, paletes e caixas). Carga que ele ainda não confirmou por inteiro aparece também, marcada com ⌛, em vez de sumir da lista.
🔒 Só as dele, garantido: o corte é pelo id do motorista logado, nunca pelo nome, e vale antes de qualquer modo ou filtro — nenhum caminho mostra a carga de outro. As opções dos filtros saem das cargas dele.
🚦 A aba 🚚 Entregar NÃO mudou: lá a janela de 7 dias é regra de trabalho (é o que ele ainda pode confirmar). Mexer nela mudaria o que aparece pra confirmar.
🔧 Por dentro: motCargasDele/motCargasFiltradas/motConsultaHTML; o minhasCargas (7 dias) ficou intacto. 24 checagens em tests/motorista-app-consulta.test.mjs. Só tela — não precisa do Luan. Com esta, a consulta está nos quatro lugares: aba Escalas, app JP ESCALA, app da Expedição e app do motorista.
v2.37.697
📐 A CAIXA PARECIDA como referência de velocidade. Você pediu: "podia pegar uma caixa mais próxima do tamanho pra fazer uma comparação e chegar num número mais assertivo".
🔍 Por que faz falta: caixa NOVA não tem velocidade em lugar nenhum — a máquina entra no preço só com os 0,5 h de acerto e o orçamento sai barato demais. Foi o que aconteceu na ALPACK ("⚠ sem velocidade").
✅ Como funciona: com as medidas preenchidas, o item mostra 📐 caixa parecida: REF (cliente · 310×210×160 mm · onda B · 5% de diferença média) com as velocidades dela por máquina, e um botão "usar estas velocidades". Nada entra sozinho — velocidade chutada vira preço errado, e preço errado vira prejuízo calado. Depois de usar, dá pra tirar com um clique.
🎯 Quem ela escolhe: mesma família de máquina (corte e vinco não é referência de maleta e vice-versa), medida mais próxima, e onda igual desempata. Caixa sem velocidade cadastrada, caixa inativa e a própria caixa ficam fora. Acima de 60% de diferença ninguém é parecido: a tela diz que não achou, em vez de sugerir qualquer coisa.
🔗 Na conta: a ordem é cadastro da própria caixa → histórico real dela → caixa parecida → capacidade padrão. O dado da própria caixa sempre manda. A memória do orçamento guarda de qual caixa veio a velocidade, então o 🧮 Pré-cálculo e o 📊 Pós-cálculo mostram a origem.
🔧 Por dentro: jpCaixaParecida (js/08, função pura) + orcParecidaTela/orcVelRefUsar/orcVelRefTirar; ctx.velRef entra na cadeia do orcIntVelocidade (js/22) entre o histórico e a capacidade padrão; o item guarda velRef. 22 checagens e 5 mutações em tests/caixa-parecida-velocidade.test.mjs. Sem servidor, sem Luan.
v2.37.696
🚚📜 App da Expedição: a mesma consulta, no Histórico. Você pediu: "agora quero a mesma consulta no app da Expedição". Ela entrou no 📜 Histórico — a tela que já era de consulta e já tinha abas — e não no card "Caminhões da escala hoje" da tela inicial, que é card de ação (tocar e iniciar a carga).
📅 Barra Só o dia · Período · Todas com filtros por motorista, caminhão e cliente. Ela nasce em Todas, então a tela continua mostrando tudo como antes; os filtros valem também nas abas Por carga e Por motorista que já existiam.
📅 Aba nova 📅 Por escala: agrupa por data (mais recente em cima, hoje marcado), mostra cada viagem da escala com o que a carga levou (paletes, caixas, peso, hora que concluiu) e traz as cargas sem viagem lançada no card tracejado. Viagem sem carga diz isso, em vez de ficar muda.
📊 Uma linha de resumo diz o recorte: quantas cargas, quantas concluídas, quantas viagens na escala e quantas sem viagem — e avisa quando há filtro ligado.
🔧 Por dentro: mesmas réguas da aba Escalas (v2.37.689) e do app JP ESCALA (v2.37.692), escritas no próprio app; o casamento viagem↔carga virou expCargasDaViagem (estava embutido no calcularStatusViagem) — uma régua só, senão a mesma carga apareceria duas vezes. 23 checagens em tests/expedicao-app-consulta.test.mjs. Só tela — não precisa do Luan.
v2.37.695
💼 A comissão do vendedor aparece no orçamento — e entra na conta do que sobra. Você pediu: "o valor da comissão quando seleciona o vendedor também tem que aparecer" e "no cálculo, quanto vai ser pago de comissão pro vendedor".
✅ Na tela: logo abaixo do vendedor, o orçamento mostra a % e o R$ — no item que você está montando, nos itens já na lista e o total. Se o cliente tem vendedor mas não tem % cadastrada, a tela avisa em vez de mostrar zero calado (o % é de Cadastros ▸ Clientes ▸ Comissão, a mesma régua do Painel de Custos).
🧮 No 🧮 Pré-cálculo do gestor: linha própria por caixa (− comissão do vendedor X%) e o total no resumo. A sobra passa a descontar a comissão — é dinheiro que a fábrica paga por aquela venda. Sem vendedor ou sem %, nada muda.
📦 Caixa nova: a prévia de como fica no palete. Você pediu: "quando não tem caixa cadastrada tem que aparecer como vai ficar no palete". Agora aparece a montagem inteira — lastro × camadas × amarrado = N caixas por palete, a medida do palete e, com a quantidade digitada, quantos paletes dá e a composição ("20 × 2.450 + 1 × 1.000").
🔍 Por que não aparecia: esse texto era escrito desde a v2.37.600 num elemento que nunca tinha sido criado na tela — a paletização padrão entrava no cálculo calada. Mesma família do campo de fechamento (v681) e da aba de insumos (v686). O que você digitar em "Caixas por palete" continua mandando no padrão.
🔧 Por dentro: orcComissaoPct/orcComissaoDoItem/orcComissaoHint (js/08, a condição do js/13 copiada, não reinventada); comPct/comissaoUn no jpPreCalculoItem (js/72); #orc-comissao-hint e #orc-it-fv-hint no sistema.html. 17 checagens e 4 mutações em tests/comissao-e-previa-palete.test.mjs, mais 5 checagens e 1 mutação no precalculo-relatorio. Sem servidor, sem Luan.
v2.37.694
🏭 A rota do orçamento agora VEM DO CADASTRO DA CAIXA — e as máquinas do MEIO entram no preço. Você disse: "no cadastro de caixa já tem corte e vinco e depois coladeira, e na hora do orçamento é só colocar isso; e o caminho, se tiver máquina do meio, já aparecer também".
✅ Escolheu a caixa cadastrada, a rota vem pronta: 1ª máquina + processos do meio + fechamento, do 🏭 Roteiro de produção do cadastro. Embaixo do campo aparece a corrente inteira, igual à do cadastro: Máq. A Corte e Vinco → ⚙️ Acopladeira → 📦 Coladeira → 🚚 Expedição, e a tela diz que a rota veio do cadastro. Se você escolher outra rota na mão, ela manda e não é reescrita.
⚙️ Máquina do meio custa: acopladeira, verniz, o que estiver em ⚙️ Máquinas como processo do meio entra no custo com a velocidade do cadastro dela e o custo-hora dela — antes uma caixa que passa na acopladeira era orçada como se não passasse. Máquina do meio sem custo-hora cadastrado continua fora, com aviso, igual às de fábrica.
📌 O meio vai gravado no item, então segue pra memória do orçamento, pro 🧮 Pré-cálculo do gestor e pro 📊 Pós-cálculo — que compara máquina por máquina, incluindo as do meio.
🔧 Por dentro: orcRotaDaCaixaCadastro (js/08) lê maqCorte + roteiroMeio + fechamento; ctx.meio viaja no orcCtxDoItem; _orcIntComMeio e _orcIntMaqCadastro no js/22 (chave do cadastro, velPadrao, custo-hora pelo MAQ). 22 checagens e 5 mutações em tests/rota-do-cadastro-com-meio.test.mjs. Sem servidor, sem Luan.
v2.37.693
🧰 O acessório de UMA caixa só (a alça) e o SERVIÇO EXTERNO agora entram no preço. Você disse: "cadastrei o grampo, mas cada caixa usa uma quantidade e não tem como definir isso"; "existe caixa que tem esse acessório a mais e isso tem que colocar no orçamento na hora de fazer; existe o serviço externo também".
🔍 O que era: o insumo só sabia responder por característica (caixa grampeada, colada, impressa, com filme, amarrada) — perfeito pro grampo e pra cola, inútil pra alça: marcada como "sempre", ela entraria em todas as caixas.
✅ Agora tem dois lugares, a mesma lista: no cadastro da caixa, seção 🧰 9b · Insumos desta caixa; e no item do orçamento, campo 🧰 Acessórios e serviços desta caixa — que já vem preenchido quando você escolhe uma caixa cadastrada e dá pra mexer na hora, só naquele orçamento (um pedido leva a alça, o outro não). Cada linha tem a quantidade por caixa: 2 alças numa, 4 noutra. Vazio = a quantidade do cadastro.
🤝 Serviço externo (terceirizado): no ⚙ do insumo (📒 Financeiro ▸ 🧰 Insumos do Orçamento) marque "É serviço externo" — montagem, verniz, laminação, corte fora. Entra na mesma lista e no mesmo custo, e aparece com 🤝 nas telas e no 📋 Custo completo.
🎯 O interruptor que segura a alça: no ⚙ existe "Só nas caixas que listarem este item". Com ele marcado, o insumo nunca entra sozinho — só na caixa que o escolheu. Sem ele, o item volta a valer pra todas, como antes. Grampo e cola continuam entrando pela rota, sem precisar de lista.
📌 O que você escolhe no item vai gravado na memória do orçamento, então aparece no 🧮 Pré-cálculo do gestor e no 📊 Pós-cálculo. O elo é a chave do insumo: renomear ele no Financeiro não desliga a alça de nenhuma caixa.
🔧 Por dentro: `insumosCaixa: [{key, consumo}]` na caixa (jsonb, sem migration) e no item; `_daCaixa` + `soNaCaixa`/`servico` no js/71; seção 9b (js/08) e campo do item (sistema.html + `orcInsumosSet/Add/Del/Qtd`); `ctx.insumosCaixa` no `orcCtxDoItem`; 🤝/(desta caixa) na linha do js/72. 25 checagens e 6 mutações em tests/insumo-da-caixa-alca.test.mjs. Sem servidor, sem Luan.
v2.37.692
📱📜 App JP ESCALA (tablet): a mesma consulta da aba Escalas. Você pediu: "agora quero a mesma consulta no app JP ESCALA do tablet".
📅 Embaixo do Ontem / Hoje / Amanhã entrou a barra Só o dia · Período · Todas, com os filtros por motorista, caminhão e cliente e o "limpar". Fora do dia a lista vem agrupada por data (mais recente em cima, hoje marcado, "abrir" leva pro dia), e as cargas sem viagem lançada entram com a data delas, no card tracejado. Cada viagem mostra o que a carga levou (paletes, caixas, peso, hora que concluiu).
📊 Os três números do topo passam a ser do recorte: viagens (mais "+N" cargas soltas), caminhões e concluídas. No modo dia continuam iguais ao de sempre. "Postar escala do dia" segue postando o dia escolhido.
🔧 Por dentro: mesmas réguas do sistema (v2.37.689) escritas no próprio app (viagensFiltradas, cargasSemViagem, popularFiltros; o card virou cardViagem); o casamento viagem↔carga é o cargasDaViagem que já existia lá. 19 checagens em tests/escala-app-consulta.test.mjs. Só tela — não precisa do Luan.
v2.37.691
🛣️ A ROTA DA CAIXA, escolhida no item do orçamento. Você pediu: "pra calcular o preço tem que colocar a rota da caixa: corte e vinco → coladeira, slotter → coladeira".
✅ Onde: no item do orçamento, campo 🛣️ Rota da caixa, com 6 rotas: Corte e Vinco → Coladeira · Corte e Vinco → Grampeadeira · Corte e Vinco (sai pronta) · Slotter → Coladeira · Slotter → Grampeadeira · Slotter (sai pronta). Deixando em "automática", vale a dedução de sempre (estilo da caixa + fechamento). Embaixo do campo a tela diz qual rota entrou no preço e avisa se alguma máquina da rota está sem custo-hora.
🔗 Uma tabela, três pontas: a rota escolhida manda no preço (as horas de cada máquina no custo completo e na memória do item), na rota do pedido quando o orçamento vira pedido (roteiro, máquina de corte e acabamento — o modal de converter mostra o acabamento travado "rota escolhida no item") e no 📊 Pós-cálculo, que compara máquina por máquina. Sem escolher nada, tudo fica byte a byte como era.
📌 Rota escolhida manda até sobre o fechamento do cadastro da caixa: é a pessoa dizendo por onde a caixa passa. Se a caixa já é cadastrada com fechamento diferente, o cadastro não muda — só este orçamento/pedido.
🔧 Por dentro: tabela ORC_ROTAS (js/22) usada por orcIntMaqsDoItem (preço) e orcRotaDoItem (js/08, rota do pedido — o orcParaPedidoConfirmar e o modal de converter leem dela); ctx.rota no orcCtxDoItem; campo orc-it-rota gravado em it.rota. 20 checagens e 5 mutações em tests/rota-explicita-no-item.test.mjs; rota-completa-poscalculo e aceite-vira-pedido passaram a ler a função nova. (Era pra ser a 689; a main ganhou 689 e 690 de outras frentes no caminho — e o selo ATUAL, que tinha ficado na 689, voltou pro topo.) Sem servidor, sem Luan.
v2.37.690
🌳 FSC – Fase 1 (Cadeia de Custódia, norma FSC-STD-40-004). Nasceu o módulo 🌳 FSC no menu, com três telas: Painel (saldo de crédito por grupo, créditos a vencer em 60 dias, % do faturamento do mês com claim, rendimento × fator, fornecedores vencidos, validade do certificado, notas bloqueadas pela trava), Cadastros (certificado da empresa com os textos da nota, grupos de produto, fator de conversão com vigência — nunca se sobrescreve —, verificação do fornecedor no FSC Search com anexo, ajustes) e Relatórios (os 6 que o auditor pede, com Excel/CSV: resumo anual de volume, extrato da conta, NFs de saída com rastreio NF → OP → rolos → NF de entrada → verificação do fornecedor, NFs de entrada, fornecedores, rendimento real × fator).
📦 Entrada com claim: ao importar a NF de papel (PCP e app da Qualidade) a tela mostra o claim detectado no XML (infAdProd, infCpl, descrição) e o código COC; quem decide é a API: claim no enum + código batendo com o cadastro do fornecedor + verificação no prazo (R1/R8) — senão entra como Não FSC e avisa. Cada entrada FSC vira crédito = kg × fator vigente, que expira em 24 meses (robô diário, R9). O rolo herda o claim e a etiqueta da bobina imprime.
🧾 Venda com claim (a trava R3): cliente pode "exigir FSC" no cadastro e o pedido nasce marcado; o vendedor marca/desmarca no app e vê o saldo (R4). Na baixa (é quando a nota real do Sectra existe) o sistema confere grupo, certificado e saldo, pede o nº da NF e debita FIFO; sem saldo, oferece baixar SEM claim. Desfazer a baixa estorna sozinho. A folha "Imprimir pro faturamento" já sai com a frase do infAdProd/infCpl (ou a tarja SEM CLAIM); a pré-nota valida igual e preenche o infAdProd pelo template do certificado. Romaneio e etiqueta de palete imprimem o claim.
🔒 Trilha em tudo que é FSC (quem, quando, antes, depois — R12); nada se apaga, só inativa. Ajuste manual só com o poder fsc-ajuste (Responsável FSC) e justificativa (R11). Estoque, papel e pré-nota de quem não é FSC continuam byte a byte iguais — o FSC é um livro paralelo.
🐛 De caminho: a pré-nota travava em "Calculando…" quando a migration 043 não estava aplicada (`b` indefinido) — corrigido; o app da Qualidade passou a mandar os itens da NF pra API (antes só o cabeçalho).
⚠️ Precisa do Luan: npm run db:migrate (migration 045) + pm2 restart all. Até lá a tela avisa "módulo FSC não instalado" e nada trava.
v2.37.689
📜 Escalas: agora dá pra ver TUDO que já foi feito, com data, e consultar por motorista, caminhão e cliente. Você pediu: "não consigo visualizar todas as cargas, somente a do dia; quero ver a do dia e também todas que já foram feitas e concluídas, com datas, e consultar por motorista, por caminhão e por carga (cliente)".
📅 Três modos, na aba Escalas: Só o dia (o de sempre, agrupado por caminhão), Período (de/até, nasce nos últimos 30 dias) e Todas. Fora do dia a lista vem agrupada por data, a mais recente em cima, com o dia de hoje marcado — e cada data tem o link "abrir o dia".
🔍 Filtros por motorista, caminhão e cliente, que valem nos três modos. As opções saem do próprio dado (escala + cargas), então viagem antiga com motorista que não está mais no cadastro continua encontrável. "ACH-9A34" e "ACH9A34" são o mesmo caminhão; o cliente casa em qualquer destino da viagem.
🚚 As cargas que não têm viagem na escala também entram na consulta, com a data delas (a escala ficou vazia de 29/07 até agora e a história dessas semanas só existe na carga): aparecem como "carga sem viagem lançada", com motorista, placa, clientes, paletes, caixas, peso, se concluiu e a hora — e um botão pro Histórico. A carga que JÁ casa com a viagem (pelo id da escala, ou placa+dia nas antigas) aparece dentro da viagem, nunca duas vezes: é a mesma régua que pinta o status da viagem.
🌐 Cada viagem mostra o que a carga dela levou: paletes, caixas, peso, hora que concluiu e os clientes — no dia e na consulta. O resumo em cima conta viagens, cargas sem viagem, concluídas, caminhões e motoristas do recorte. O badge da aba continua sendo o de HOJE.
🕑 Plano de Carga não abre mais no KININO de uma escala velha. Você disse: "toda vez que abro o Plano de Carga já vem o cliente KININO, de uma escala que eu havia feito há muito tempo". A lista de viagens era por data crescente: a viagem mais antiga ainda "programada" (ninguém deu baixa) era a 1ª opção, e o plano novo herda a 1ª opção. Agora o seletor vem com hoje e as próximas primeiro; as antigas sem baixa ficam num grupo próprio no fim, e o plano novo só cai numa antiga se não sobrar mais nada — e aí um banner 🕑 diz de que dia ela é e pede pra dar baixa na Escala (agora dá pra achá-la lá, pela consulta).
🔧 Por dentro: escViagensFiltradas/escCargasSemViagem/escPopularFiltros no js/08; o casamento viagem↔carga virou escCargasDaViagem (o status da viagem usa o mesmo); plcViagemAntiga no js/22. 41 checagens em tests/escala-consulta.test.mjs + 10 em tests/plano-carga-viagem-antiga.test.mjs. Só tela — não precisa do Luan. O app JP ESCALA (tablet) continua só no dia por enquanto.
v2.37.688
📊 Simular quantidades agora diz QUANTO GANHA em cada faixa (1.000 · 2.000 · 5.000 · 10.000…), quantos paletes e quantas horas de máquina. Você pediu: "1 mil caixa quanto ganha, e 5 mil, 10 mil, pra fazer um comparativo".
✅ Em cada cartão: bloco 💰 Quanto ganha nesta quantidade — venda (sem IPI) − impostos por dentro (e juros do prazo) − custo completo = sobra, em R$, % e por caixa, e quanto a mais/menos que a 1ª faixa. Embaixo, 📦 paletes (a mesma conta do item: cadastro da caixa → padrão → digitado, com a composição "2 × 1.000 + 1 × 500") e ⚙️ horas por máquina. A caixa coletiva entrou como linha no cartão.
📦 Paletização vai junto pra caixa nova. Quando o orçamento vira pedido e a caixa ainda não existia, ela nasce com as caixas por palete do item — antes nascia sem, e o próximo orçamento/PA/expedição recomeçava do zero. O custo do palete entra pelo insumo: 🧰 Insumos do Orçamento ▸ "Pallet" ▸ ⚙ base por pallet + preço — e como a quantidade já diz quantos paletes vão, o R$ do palete entra sozinho no pré-cálculo.
📦 Caixa coletiva aparece na conta. Ela já entrava no custo desde a v599, mas sem linha — agora o 📋 Custo completo, a memória do item, o 🧮 Pré-cálculo do gestor e o simulador mostram "📦 Caixa coletiva: 20 coletivas 'X' × R$ 22 — cabem 50 caixas em cada". Escolhida e sem preço sai riscada com o motivo; não escolhida, não aparece.
🔩 Grampo e cola pela ROTA, também na caixa nova. O insumo já sabia entrar só na caixa grampeada/colada ("Só quando") e o grampo já contava pela aba (um a cada N mm, com mínimo) — mas a caixa NOVA no orçamento não dizia o fechamento pros insumos, então grampo e cola saíam de graça nela. Agora o campo 🔒 Fechamento da caixa nova chega na conta dos insumos; caixa cadastrada com fechamento continua mandando.
🔧 Por dentro: orcSimGanho (pura) + cartão do orcSimRender (js/08); paletizacao.caixasPorPalete na caixa criada pelo orcParaPedidoConfirmar; linha t:'coletiva' no _linhasCustoCompleto (js/72); _cxIns no orcCtxDoItem. 22 checagens e 5 mutações em tests/simulador-ganho-paletes.test.mjs; caso 10 no tests/aceite-vira-pedido.test.mjs. Sem servidor, sem Luan.
v2.37.687
🧮 Relatório do PRÉ-CÁLCULO, separado do orçamento: o orçamento vai pro cliente, o pré-cálculo vai pro gestor avaliar o custo de cada operação. Você pediu exatamente assim.
✅ Onde: 💰 Orçamentos ▸ Ver/Enviar ▸ botão 🧮 Pré-cálculo (gestor), ao lado do 🖨️ Imprimir. Abre a janela de impressão (dá pra "Salvar como PDF"), em A4 retrato, com tarja vermelha de DOCUMENTO INTERNO no topo e no pé. Só admin e financeiro (ou quem está na lista de acesso a custos) veem o botão — tem custo e margem.
📋 O que sai: resumo por caixa (custo/cx, preço praticado × sugerido, sobra por caixa e no item, %); horas de máquina somadas; e, caixa por caixa, o custo de cada operação: papel, cada máquina com horas × custo-hora, tinta, insumos, frete, ferramenta — o que não está cadastrado sai riscado, com o aviso de onde cadastrar — e a conta até o preço (margem, impostos por dentro, juros do prazo, IPI por fora). Fecha com o preço pelo custo (custo líquido, margem zero, R$/kg equivalente).
🧾 A sobra = preço praticado − impostos por dentro − juros do prazo − custo completo. É a mesma régua que fez o preço sugerido; sem IPI, que é repassado. Na ALPACK (0037): custo R$ 1,1935, praticado R$ 2,0508 → sobra R$ 0,2984/cx = R$ 298,42 (14,6%).
📌 Lê a memória gravada no item, não recalcula. Caixa orçada antes da v2.37.630 (quando a memória passou a existir) sai com aviso: reabra o item e salve, que a memória entra. Preço negociado na mão aparece como "▲/▼ x% do sugerido".
🔧 Por dentro: jpPreCalculoItem / jpPreCalculoRelatorioHTML / jpPreCalculoImprimir / jpPreCalculoPode no js/72; botão orc-ver-precalculo ligado no js/08 (initOrcamentoModule + abrirOrcVer); papel pelo js/68. 28 checagens e 6 mutações em tests/precalculo-relatorio.test.mjs. Sem servidor, sem Luan.
v2.37.686
🧰 A aba "Insumos do Orçamento" que o custo completo apontava — e que não existia. Você mostrou: o 📋 Custo completo dizia "nenhum insumo cadastrado — 📒 Financeiro ▸ 🧰 Insumos do Orçamento", e o Financeiro tinha 14 abas, nenhuma com esse nome.
🔍 O que era: o aviso nasceu na v2.37.598 apontando pra uma tela que nunca foi construída. O cadastro morava dentro de uma caixinha fechada em 🖨️ Lançamentos ("Gerenciar insumos da lista 'O que comprou'"), e por isso a lista está vazia na produção desde 19/08: grampo, cola, fita, stretch e pallet saem de graça no preço de todo orçamento.
✅ Agora existe: 💰 Financeiro ▸ 🧰 Insumos do Orçamento (pra admin, PCP e financeiro — os mesmos de Lançamentos). Mostra cada insumo com do que depende (caixa, chapa, amarrado, pallet, pedido), consumo, preço e só quando entra (caixa grampeada, colada, com filme…), e diz na cara: 💰 entra no preço, ⚠ sem preço (tem base, mas R$ em 0 — não entra) ou só rótulo. O ⚙ é o mesmo "como entra no preço" de Lançamentos; é a mesma lista — gravar num lado redesenha o outro.
➕ Cadastrar: digite o nome e clique em "Adicionar e dizer como entra no preço" — já abre o ⚙ (insumo só com nome é rótulo e não custa nada; era isso que deixava a lista sem efeito). Cola e fita que já existem como categoria de compra nos Lançamentos não entram no preço por si: precisam estar cadastradas aqui, com base e R$.
📌 Onde fica cada custo do pré-cálculo: insumos → aqui; frete → Orçamento ▸ Configurações ▸ Frete padrão por entrega (um valor por entrega, dividido pela quantidade do item); custo-hora das máquinas → ⚙️ Máquinas ▸ 💰 Custo-hora; velocidade → cadastro da caixa; clichê/faca → no próprio item do orçamento.
⚠️ O que ainda NÃO dá: insumo de uma caixa só (ex.: a alça de uma caixa de corte e vinco). Hoje o "só quando" é por característica (grampeada, colada, impressa, com filme, amarrada) — um insumo com "sempre" entraria em toda caixa. Pra alça e afins falta um campo "insumos desta caixa" no cadastro da caixa/item. Fica anotado como próximo passo.
🔧 Por dentro: view cc-insumos (botão + root no sistema.html, MODULOS no js/01, PERMS no js/07, dispatcher/trava no js/13); renderCcInsumos no js/13 lendo CC_INSUMOS e os rótulos do js/71; ccAddInsumo(inputId) + _insumosRedesenhar. 23 checagens e 6 mutações em tests/insumos-orcamento-tela.test.mjs. Sem servidor, sem Luan.
v2.37.685
🛣️📊 A rota completa: do orçamento (pré-cálculo) até o pós-cálculo, com as MESMAS máquinas nas quatro pontas. Você pediu: "já fizemos orçamento com pré-cálculo, quero a rota completa até o pós-cálculo".
🔍 O que era: no seu teste de hoje (ALPACK, Cx p, 1.000 cx, orçamento nº 0037) a rota andou inteira — o aceite virou pedido sozinho, a fábrica apontou Corte e Vinco e Coladeira, o pedido ficou pronto e o 📊 Pós-cálculo (💰 Financeiro) já abre com ele. Mas a tela dizia "Coladeira: rodou fora do orçamento" e "Orçado na v—". Causa: o orçamento de caixa de corte e vinco cobrava só a Corte e Vinco, mesmo com fechamento cola (33 das 44 caixas de C&V do cadastro são coladas). O pedido já nascia com a rota certa (C&V → Coladeira) e a fábrica rodava a Coladeira — só o preço fingia que ela não existia, e o pós-cálculo acusava a diferença em toda caixa dessas.
✅ Conserto 1 (o pré-cálculo cobra a rota inteira): caixa de corte e vinco com fechamento cola → Corte e Vinco + Coladeira; grampo → + Grampeadeira; sem fechamento → só C&V, como sempre. Vale o fechamento da caixa cadastrada; caixa nova usa o campo 🔒 Fechamento da caixa nova (v2.37.681) — a MESMA ordem que o aceite automático usa pra montar a rota do pedido. Maleta/RSC não muda nada.
⚠️ O que muda no preço: caixa de C&V colada/grampeada passa a ter a hora da Coladeira/Grampeadeira no custo (ex.: 1.000 cx a 7.000 cx/h + 0,5 h de acerto = 0,64 h × custo-hora). Orçamento antigo reaberto avisa a diferença (> 0,5%) e não muda sozinho. Máquina sem custo-hora cadastrado continua fora, como hoje.
✅ Conserto 2: a memória de cálculo grava a versão em que foi orçado (o pós-cálculo mostrava "v—" em todo pedido).
📍 Onde está o pré-cálculo: 💰 Orçamentos ▸ no item, logo abaixo do preço sugerido, botão 📋 Custo completo (papel, máquinas com horas, tinta, insumos, frete, ferramenta) e o preço pelo custo ao lado. É essa memória que viaja pro pedido e que o pós-cálculo compara.
📌 O que ainda depende de cadastro pra rota fechar de verdade: (1) a velocidade da Corte e Vinco — hoje está "sem velocidade" e o orçamento põe só os 0,5 h de acerto; cadastre a velocidade de C&V na caixa, ou deixe a fábrica apontar com horário de início e fim (a média entra sozinha nos próximos); (2) o ⏱ tempo previsto no app do operador nasce desligado (Configurações); (3) apontamento com início = fim (como o teste de hoje, 15:42 → 15:42) vale 0 h — o pós-cálculo mostra 0,00 h e "▼ 100%", que é a verdade do registro.
📊 Quem entra no pós-cálculo hoje: só pedido que nasceu de orçamento da v2.37.630 em diante (é quando a memória passou a ser gravada) e já tem produção apontada. Na carteira: 1 (o ALPACK). Os outros 18 nascidos de orçamento (KININO 0004/0027, DEUSA 0026, JESSE 0009) são de antes e não têm memória — não aparecem, de propósito.
🔧 Por dentro: orcIntFechamentoDoItem + orcIntMaqsDoItem (js/22, chave do cadastro em cada máquina); ctx.fechamento no orcCtxDoItem (js/08, mesmo cano das 5 chamadas); _versaoApp (js/72, lê o selo da página). 34 checagens e 6 mutações em tests/rota-completa-poscalculo.test.mjs (ponta a ponta: js/22 → js/72 → js/08 → js/01 → js/77); tests/custo-hora-maquina 10d atualizado pra regra nova. Sem servidor, sem Luan.
v2.37.684
🚚 Plano de Carga: aviso quando o arraste inverte a ORDEM DE ENTREGA. Você pediu: "agora quero o aviso quando o arraste inverte a ordem de entrega".
📏 A régua: o baú descarrega pela porta. Quem entrega antes tem que estar mais perto da porta na mesma faixa, e nunca embaixo de quem entrega depois. O automático já monta assim; o arraste é livre, então o sistema avisa — nunca trava.
👆 Onde aparece: (1) no texto embaixo do baú enquanto arrasta, dizendo quem ficaria na frente (ou em cima) de quem; (2) na pergunta ao soltar, também no chão (antes só empilhar perguntava) — confirmou, vai; (3) num banner 🚚 fixo enquanto o desenho estiver invertido, com a lista, pra ninguém liberar sem ver. Girar também avisa se o palete girado trocar de faixa e ficar na frente de quem entrega antes.
✅ Não avisa à toa: palete na frente mas em outra faixa não bloqueia ninguém; palete da 1ª entrega em cima do da 2ª está certo. Só conta quem entrega depois ficando na frente (ou em cima) de quem entrega antes.
🔧 Por dentro: plcInversaoEntre/plcInversoesDoPlano (mesma faixa = as larguras se cruzam; na frente = começa depois do fim do outro; em cima = z0 no topo do outro). +15 checagens em tests/carga-arrastar-planta.test.mjs (82 no total). Só tela — não precisa do Luan.
v2.37.683
↻ Plano de Carga: agora você também GIRA o palete na mão. Você pediu, logo depois do arraste: "agora quero girar o palete na mão também".
👆 Como: todo palete retangular na planta ganhou um botãozinho ↻ no canto de cima. Um toque gira 90° no lugar (o centro fica onde estava; se sobrou pra fora da parede, ele encosta nela). Pegou a base de uma pilha, a pilha inteira gira; pegou o de cima, só ele. Palete quadrado não tem o botão — girar não mudaria nada.
⛔ Se girado não cabe ali (invade o vizinho ou sai do baú), o sistema avisa e não gira: mova o palete pra onde tem espaço e gire de novo. Palete que está em cima de outro continua em cima depois de girar — nunca cai pro chão sozinho.
💾 Fica no plano como o arraste: sobrevive ao Remontar, ao Salvar e ao reabrir, e o ajuste salvo pela v2.37.682 (antes do giro existir) continua valendo. Mover e girar o mesmo palete é um ajuste só. "Limpar todos" no banner ✋ volta tudo ao automático.
🔧 Por dentro: plcGirarPilha; o posManuais passou a guardar a orientação (prof/larg/girado), e a identidade da pilha aceita o mesmo palete com as medidas trocadas. +18 checagens em tests/carga-arrastar-planta.test.mjs (67 no total). Só tela — não precisa do Luan.
v2.37.682
✋ Plano de Carga: agora você ARRASTA os paletes na planta. Você pediu: "quero mexer nos paletes, arrastar aonde tem espaço pra gerar mais espaço dentro do limite do caminhão" e "colocar um palete em cima do outro, porque a CX 20 cabe em cima da CX 01·P".
👆 Mover: na Planta do piso, pegue um palete com o mouse (ou o dedo, no tablet) e solte onde tem espaço. Ele gruda na parede do baú e no palete vizinho quando chega perto, então encostar na lateral é só arrastar até lá. Pegou a base de uma pilha, a pilha inteira vai junto; pegou o de cima, só ele se mexe (dá pra desempilhar).
⬆️ Empilhar: solte um palete em cima de outro (mais da metade dele por cima) e ele sobe pro topo daquela pilha, centrado. A borda fica verde quando vai empilhar, azul quando vai pro chão e vermelha quando não dá — e um texto embaixo do baú diz o que vai acontecer se soltar.
⛔ O que não passa nem confirmando: sair do baú, passar da altura (teto + folga da ⚙️), atravessar outro palete, ficar no ar sem apoio. ⚠️ O que avisa e deixa você decidir: palete de cima que não casa com a base fora das folgas, base parcial (·P), empilhar em cima de outro cliente. Aparece a pergunta com os avisos; confirmou, vai.
💾 Fica no plano: o que você arrastou sobrevive ao Remontar, ao Salvar e ao reabrir — o automático monta o resto e respeita o seu desenho (o "apertar o arranjo" da ⚙️ pula onde você mexeu, como já pulava pros outros ajustes). A isométrica, o romaneio e o app do expedidor desenham do jeito que você deixou. Se a carga mudar e a pilha não for mais a mesma (outro tamanho, outra contagem), o ajuste é descartado e o banner diz qual e por quê — nunca vai parar num palete que você não arrastou.
↩ Voltar ao automático: "limpar todos" no banner ✋ de ajuste manual. Plano que a doca já começou a bipar não aceita arraste (o desenho ali é das bipagens) — monte um + Novo plano.
🔧 Por dentro: PLC.posManuais entra por cima do motor no fim do plcGerarPlano (o motor não mudou); chave estável por pilha (cliente|modelo|ordinal). 49 checagens em tests/carga-arrastar-planta.test.mjs; os 14 testes de carga que já existiam seguem passando. Só tela — não precisa do Luan.
v2.37.681
📦❌ Caixa finalizada que NÃO ENTRAVA no Estoque PA (nem no app da Expedição). Você pediu, como cliente ALPACK (Cx p, 1.000 cx, 06/09): "já finalizado e não está no estoque".
🔍 O que era: o pedido nasceu do aceite automático do orçamento com a rota só Corte e Vinco (a caixa era nova e o aceite assumia "sem fechamento" pra corte e vinco). O operador fechou na Coladeira e paletizou lá. A porta do Estoque PA era a ÚNICA conta do sistema que decidia a etapa final pela ROTA do pedido; o "Produzido", o recálculo, a etiqueta e o resto decidem pelo que foi lançado. As duas discordaram, o palete foi recusado e a caixa nunca entrou — calada. A Expedição lê a mesma lista, por isso a ALPACK não aparecia lá também.
📊 Medido na carteira: 18 pedidos nessa situação. 4 estão em "Pronto p/ carregar" SEM linha no PA — TRANSBERNAL TAMPA 10KG (23860), EMPORIO PRIME tampa e fundo (24064) e a ALPACK — nenhum com saída, carga ou marca do ✕: nunca tinham entrado. Os outros 14 já foram entregues e continuam fora, como devem.
✅ Conserto 1 (a porta): o Estoque PA passa a perguntar pela produção real, a mesma régua de todo o resto. Palete gravado no fechamento entra mesmo que o pedido tenha nascido com a rota errada. E o ♻️ Recalcular roda a mesma varredura da importação: clique nele e as 4 linhas entram na hora (antes só entrariam quando chegasse registro novo de algum operador).
✅ Conserto 2 (a origem): no item do orçamento, quando a caixa é NOVA, aparece o campo 🔒 Fechamento da caixa nova (cola / grampo / sem). O sistema já lia esse campo desde a v2.37.600 — ele só nunca tinha entrado na tela. O aceite automático e o modal de converter usam o que você marcou; caixa já cadastrada continua mandando. Sem marcar nada, fica o padrão de sempre.
🔧 Por dentro: adicionarCaixasNoEstoque (js/03) usa processoFinalDe + etapaDoRegistro; varredura virou estVarrerRegistrosComPalete (hook + ♻️); orcAutoConverterDoAceite lê it.fechamento. 31 checagens e 6 mutações em tests/estoque-palete-fora-da-rota.test.mjs. Sem servidor, sem Luan.
v2.37.680
📋✉️ O orçamento sai por e-mail sozinho: pro cliente com o link de aprovar, pro vendedor com o link do app. Você pediu: "quando mandar orçamento tem que ir pro vendedor e pro cliente por e-mail; pro cliente o link de aprovar, pro vendedor o link do app dele".
✅ Quando sai: na hora em que você aprova o preço (é quando o orçamento fica pronto pro cliente — antes disso o link nem abre). E dá pra reenviar pelo botão novo ✉️ E-mail automático (cliente + vendedor) no Ver/Enviar. O 📧 E-mail de sempre continua lá, agora chamado "(manual)".
👤 O cliente recebe o orçamento resumido (caixas, quantidades, preço, total, IPI, pagamento, validade, vendedor) e o botão "Ver e aprovar o orçamento" — o mesmo link aprovar.html do botão 🔗, onde ele confere as caixas e aprova com o nome.
🤝 O vendedor recebe (em todos os e-mails da ficha dele) o aviso de que foi pro cliente, o mesmo resumo, o link do cliente pra encaminhar e o botão "Abrir o app do vendedor". Se o cliente estiver sem e-mail na ficha, o vendedor é avisado disso no próprio e-mail.
🛡️ O aceite do vendedor pelo app passa a ter A MESMA VALIDAÇÃO do aceite do cliente pelo link. Antes o aceite do app só era gravado na solicitação dele; agora vai também pro servidor, no mesmo registro do link (quem assinou primeiro fica; IP e aparelho carimbados) e dispara o mesmo comprovante por e-mail pro cliente e pro vendedor. Se o servidor ainda não tiver sido reiniciado, o app segue como antes — não trava.
📋 Fica registrado no cartão: "✉️ Enviado por e-mail dd/mm · pra quem". Só vira "enviado" o que o servidor confirmou que saiu; em modo teste o cartão diz "(modo teste)".
🛑 Mesmo interruptor: vale o Desligado / Teste / Ligado da v2.37.679. Em teste, os dois e-mails caem no seu e-mail de teste com a tarja.
🔧 Por dentro: rotas novas POST /api/orcamentos/:id/enviar-email e POST /api/orcamentos/:id/aceite-vendedor (aceita o crachá do app); os links vêm da tela (ela sabe o endereço e o token). 49 checagens em tests/orcamento-email-e-aceite-vendedor.test.mjs.
⚠️ Precisa do Luan: pm2 restart (sem migration, sem npm install). Até lá a tela avisa que a rota ainda não existe, e o aceite do app segue pelo caminho antigo.
v2.37.679
🔘 Botão de LIGAR e DESLIGAR os e-mails automáticos, na tela. Você pediu: "quero um botão de ligar e desligar os e-mails". Está em ⚙ Ajustes → ✉️ E-mails automáticos, com três escolhas: ⛔ Desligado (nada sai), 🧪 Teste (nenhum cliente recebe; tudo cai no seu e-mail de teste com a tarja) e ✅ Ligado (cliente e vendedor recebem de verdade). Vale na hora, pra todos os avisos — sem mexer no .env, sem reiniciar o servidor.
👑 Só o administrador principal vê o botão e consegue mudar. Fica escrito quem mudou e quando, e a janela mostra por onde o e-mail sai, pra onde vai o teste e qual é o padrão do servidor.
⚠️ Ligar pede confirmação; desligar não (desligar é o lado seguro). E tem o "Voltar pro padrão do servidor", que apaga a escolha da tela e deixa o .env mandar de novo.
🔧 Por dentro: a escolha mora no snapshots (avisos_email_config, sem migration) e vence o .env; sem escolha, o .env vale como sempre. Rota PUT /api/pedidos/avisos/modo, só admin original. Se o banco falhar, cai no .env e fica no log. 36 checagens em tests/avisos-email-botao.test.mjs.
⚠️ Precisa do Luan: pm2 restart (sem migration, sem npm install). Até lá o botão avisa que a rota ainda não existe.
v2.37.678
📈✉️ Reajuste de preço passa a ACUMULAR — e ganha o comunicado formal por e-mail. Você deu o exemplo: "hoje vendo a R$ 10,00 o quilo, teve 7% → 10,70; mês que vem mais 5%, em cima do que já foi". É assim agora.
➕ Soma em cima do que já vale. Um reajuste novo não substitui mais o anterior: +7% e depois +5% dá 12,35% sobre o cadastro (10,00 → 10,70 → 11,235). A tela mostra a soma enquanto você digita o %, e a confirmação repete a conta. Quer substituir em vez de somar? Desliga o anterior antes. Desligar continua devolvendo o preço do cadastro na hora.
✉️ Comunicado formal, com botão. Aplicou o reajuste → abre a janela do comunicado já preenchida: Para (e-mail do cliente + todos os e-mails da ficha do vendedor + cópia pra JP, pode tirar e acrescentar), assunto, texto formal editável ("em razão do reajuste dos insumos e das condições de mercado…"), um campo de descrição específica pro que é só daquele cliente, e a tabela das caixas com o preço atual e o novo, montada sozinha. Nada sai sem clicar Enviar. O botão ✉️ também fica no cartão do reajuste, pra mandar depois ou reenviar.
📋 Fica registrado. O cartão e o histórico mostram quando o comunicado foi e pra quantos e-mails. Só vira "enviado" o que o servidor confirmou que saiu.
🐛 Um defeito antigo caiu junto: ao agendar um reajuste pra uma data futura, o anterior era encerrado na hora — e até o dia do novo o cliente caía no preço do cadastro, sem reajuste nenhum. Agora "encerrado em 05/10" quer dizer vale até 05/10.
🛑 Mesmo MODO TESTE dos outros avisos: enquanto o servidor não for liberado, o comunicado cai no seu e-mail de teste com a tarja de pra quem iria — a janela avisa isso antes de você enviar.
🔧 Por dentro: pctAcumulado e sobre no registro do reajuste (registro antigo continua valendo o % dele); rota nova POST /api/clientes/:id/comunicado-reajuste; 43 checagens em tests/reajuste-acumulado-comunicado.test.mjs.
⚠️ Precisa do Luan: pm2 restart (sem migration, sem npm install).
v2.37.677
✉️🤝 O vendedor passa a ser avisado por e-mail em TODA etapa do pedido dele — e nos e-mails que VOCÊ cadastrar na ficha dele. Você pediu: "toda vez que o Armando coloca um pedido, a JP recebe um e-mail com o pedido, e ele recebe dizendo que foi colocado com sucesso; e que foi aceito; cada etapa".
📧 Vários e-mails por vendedor. Em Cadastros → Vendedores, o campo E-mail ganhou o botão ➕ Adicionar e-mail: um campo por endereço (o Armando, o sócio dele, o escritório… quantos quiser). Todos recebem. E-mail errado barra o salvar. A lista mostra todos e avisa em amarelo o vendedor sem e-mail.
📨 Pedido lançado pelo app do vendedor → sai na hora um e-mail pro vendedor ("Pedido enviado pro PCP", com as caixas, quantidade e o preço que ele digitou) e uma cópia pra JP com o pedido inteiro. Aceito ou recusado pelo PCP → outro e-mail pro vendedor, com quem aceitou (ou o motivo da recusa).
🏭 Etapas da fábrica (programado, em produção, carregado, entregue) → o vendedor recebe sempre. O quadradinho da ficha do cliente continua mandando só na cópia do cliente — antes ele calava o vendedor junto.
🛡️ As mesmas travas de sempre: um e-mail por pedido e por etapa (editar o pedido ou mandar recado na conversa não manda nada); fila restaurada de backup não avisa; cadastro TESTE_ nunca recebe; e-mail nunca segura a gravação.
🛑 Continua em MODO TESTE até o servidor ser liberado: tudo cai no seu e-mail de teste com a tarja de pra quem iria.
🔧 Por dentro: o aviso mora no /merge do doc pedidos_vendedor (compara o que estava com o que ficou); regra pura em api/src/lib/emails-do-vendedor.js, com 38 checagens em tests/avisos-vendedor-emails.test.mjs. Chave nova no .env: AVISOS_EMPRESA_EMAIL (vazio = cai na própria caixa que envia).
⚠️ Precisa do Luan: pm2 restart (sem migration, sem npm install).
v2.37.676
📡 O contador da Slotter para de pular em lotes (120 → 135) e passa a contar de 1 em 1. O aparelho na máquina manda a contagem a cada 10 segundos, e a tela corria até o número novo em menos de 1 s e ficava 9 s parada — era isso que o olho lia como pulo. Agora o número caminha durante o intervalo entre um lote e outro: 120, 121, 122… e chega em 135 pouco antes do lote seguinte. No Mural (linha "neste pedido" e a barra ao vivo pelo sensor) e no app do operador (a dica "o sensor contou N").
⏱️ A duração é medida, não chutada. O sistema mede o intervalo real entre duas leituras do aparelho (10 s na Slotter hoje; 5 s se o ESP32 for regravado com o ritmo da ficha) e ajusta a caminhada sozinho, entre 0,9 e 12 s. Se o lote atrasar, o número para no último valor real e espera.
🛡️ As três travas de antes continuam. O número nunca mostra mais que o real (é interpolação do que já chegou, sempre por baixo — é o número que o operador confere contra a contagem dele); pedido novo ou marca nova entra direto, sem deslizar pra baixo; aparelho reiniciado zera o histórico. E as ações automáticas (🤖), o preenchimento da quantidade e o aviso de parada continuam lendo o valor real, nunca o animado.
🔄 Redesenhar o Mural não faz mais o número pular pro fim. O Mural redesenha sozinho a cada 15 s e quando o progresso do pedido muda; antes isso reiniciava a animação já no valor final (com 0,9 s ninguém via; com 9 s ficaria visível). Agora a tela guarda o que está sendo mostrado e continua de onde estava.
🔌 A tela lê o sensor a cada 2 s (era 5 s). Os 5 s não eram sincronizados com os 10 s do aparelho: às vezes a leitura nova era pega na hora, às vezes só um ciclo inteiro depois — e o lote virava 15 em vez de 10. A configuração por máquina continua sendo lida a cada ~16 s, como antes. Só roda com o Mural na tela ou produção aberta no tablet.
🔧 Só tela. Nada muda no servidor, no banco, no dado gravado nem no aparelho. Não precisa do Luan. Testes: mural-numero-suave reescrito (48 checagens, com o cenário "leituras a cada 10 s") e sensor-operador-fase2 (55 checagens).
⚠️ O dado continua chegando com ~10 s de atraso do aparelho: a caminhada preenche esse intervalo com o que já passou, nunca adivinha o que vem. Baixar o período de envio do ESP32 (a ficha aceita de 2 a 30 s) é o que encurta o atraso de verdade — e a tela já se ajusta sozinha quando isso acontecer.
v2.37.675
✉️ O cliente passa a ser avisado por e-mail sozinho — e ele escolhe do quê. São 7 avisos, marcados um a um na ficha do cliente, logo abaixo do e-mail dele: Pedido registrado, Programado, Em produção, Carregado, Entregue, Orçamento aprovado e Aprovação de caixa nova. Cada e-mail vai pro cliente e pro vendedor dele.
📧 Sai da caixa da empresa: desenvolvimento@jpmicroondulados.com.br, a conta hospedada no Terra — e não de um endereço de serviço estranho. O cliente responde e cai onde tem que cair.
🧾 Automático de verdade — ninguém clica em "enviar". O aviso mora dentro da mesma rotina do servidor que já grava o pedido, a etapa e a aprovação. Gravou, avisou.
🔑 Ninguém cadastra e-mail de novo. Usa o que já está na ficha do cliente e na do vendedor. E se o cliente estiver sem e-mail, a própria ficha avisa em amarelo na hora de marcar.
✅ O que vem marcado de fábrica: pedido registrado e as duas aprovações. As quatro etapas nascem desmarcadas — são as que você pediu pra escolher cliente a cliente.
🛑 Nasce em MODO TESTE. Enquanto não for liberado no servidor, nenhum cliente recebe nada: tudo cai num e-mail seu, com uma tarja dizendo pra quem teria ido.
🛡️ As travas que impedem virar spam. Sincronizar a carteira dez vezes no dia não reenvia nada; importação ou restauração de backup não manda nada; correção em massa de etapa também não; pedido resgatado da lixeira não avisa de novo; cadastro TESTE_ nunca recebe; e pedido novo manda um e-mail, nunca dois.
🔒 A senha da caixa nunca sai em texto puro. Se a porta do servidor de e-mail não oferecer proteção, o sistema se recusa a mandar em vez de despejar a senha da empresa na rede.
🔧 Sem biblioteca nova. O envio foi escrito com o que o Node já tem. Dependecia nova é o que matou o servidor no boot em 29/07 e deixou a fábrica ~2h sem sistema — esse caminho ficou fechado de propósito.
🐝 Um defeito antigo caiu junto: o arquivo de configuração do servidor (.env) não chegava em quem manda e-mail. Ou seja, o reset de senha por e-mail e os avisos do Desenvolvimento podiam estar calados há meses, sem uma linha de erro pra alguém desconfiar. Agora a configuração vale de verdade.
💰 O e-mail não traz preço, e isso é escolha. O valor do pedido é o unitário e o total que o cliente enxerga leva o IPI por cima. Refazer essa conta seria ter duas contas que um dia divergem — e número errado em e-mail que já saiu não desfaz.
🔍 "Por que o fulano não recebeu?" tem resposta escrita: /api/pedidos/avisos/status?cliente=NOME diz o que ele tem marcado, por qual caixa sai, pra quem iria e, se não fosse pra ninguém, por quê.
🔧 Pro Luan: falta pôr no .env os dados da caixa do Terra (servidor, porta, usuário e senha) e reiniciar. Sem migration e sem npm install. Passo a passo em PARA-O-LUAN-email-automatico.md.
⚠️ Precisa do Luan: pm2 restart e as chaves SMTP_* / AVISOS_CLIENTE no .env (modelo em .env.example). Até lá o modo é TESTE: nenhum cliente recebe nada.
v2.37.674
📦👀 Arquivar a produção deixava o pedido INVISÍVEL pro operador. Você mostrou o TANGARA 23848 · 04 FLOPS 70: em produção, com 8.670 chapas lançadas, e a Máq. A Corte e Vinco no app do operador marcando “TODOS (0)”.
🔍 O que estava acontecendo: dia 21/08 o operador finalizou o pedido no Corte e Vinco, e uns minutos depois o lançamento foi arquivado (o × do histórico). Arquivar tirava o número — por isso a barra do PCP mostrava 0 de 8.670 — mas não tirava a marca de “já terminei esta etapa”. E o app do operador esconde o que está concluído na máquina dele. Pior: essa marca vale 7 dias, e a aba ✅ Concluídos só guarda 18 horas — entre uma coisa e outra o pedido não aparecia em aba nenhuma, sem uma palavra na tela. O KININO 23873 · CX 52 estava exatamente igual (arquivado 18 segundos depois): como eram os dois únicos pedidos daquela máquina, a aba inteira ficou zerada.
✅ O conserto: arquivou o lançamento e a etapa ficou sem produção nenhuma? A marca de “concluído” é solta na hora e o pedido volta pro operador sozinho — sem precisar Reiniciar e sem perder a chapa lançada. Vale no × do histórico de produção e no 🗑️ Resetar paletes.
⚠️ Erra pro lado de não fazer: se sobrou algum lançamento vivo naquela etapa, nada é solto — ali o caminho continua sendo o ↩️ Reabrir etapa, que calcula o que falta. Pedido carregado ou entregue não é tocado, e as outras etapas que têm produção continuam concluídas. Nada é apagado: o lançamento arquivado continua riscado no histórico e a reabertura fica escrita na vida do pedido.
🔧 Por dentro: o ↩️ Reabrir etapa e a anulação passaram a usar a mesma função — duas cópias dessa decisão divergiriam sempre. Teste novo com 8 mutações (tests/anular-registro-solta-etapa.test.mjs).
✅ Não precisa do Luan: é só tela.
v2.37.673
⏸ No Diário do Operador, o dia 15/07 do Miller mostrava 580,6 horas de máquina parada — num dia que tem 24. Era a mesma parada de "esperando chapa" que ficou correndo de 03/07 a 15/07 porque ninguém apertou ▶ Retomar produção, e que está gravada em dois registros: 290h19 duas vezes.
✅ Fechou a fila: esta era a última das quatro telas que somavam parada esquecida. O 📊 gráfico, o 🎯 OEE e a ficha do operador ganharam a conta na v2.37.545; a Produtividade, na v2.37.550; agora o Diário. Todas usam o mesmo arquivo — se cada tela tivesse a sua régua, o sistema diria números diferentes da mesma máquina e ninguém saberia em qual acreditar.
👀 Aqui a parada NÃO some da tela — e não pode mesmo. Ela continua na linha do tempo, agora em âmbar e escrita "⏸ Parada esquecida — Esperando chapa · marcou 290h19 num registro que durou 6h38 · fora da conta". O Diário existe justamente pra mostrar o que aconteceu no dia; esconder o botão esquecido seria tirar dele a única coisa que ele tem pra contar. No KPI 🛑 Parado aparece um ⏸2 avisando que houve.
📅 Quanto muda: conferi os 201 dias/operador do seu banco — 7 dias deixam de mostrar tempo parado que não existiu. Miller 15/07 (580,6h → 0), Fabricio 11/08 (167,7h → 2,3h), Mayara 15/07 (35,1h → 0,9h) e mais quatro. Os outros 194 dias ficam exatamente iguais.
🍽️ Detalhe fino: refeição e troca de turno esquecidas aparecem marcadas na linha do tempo, mas não entram no ⏸N — o KPI é "min (sem refeição)", então elas nunca estiveram naquela soma e anunciá-las como "saiu da conta" seria mentira. É a mesma regra da tela de Produtividade, pra as duas não discordarem.
🔒 Nada foi apagado: as paradas seguem no histórico com a hora de início original (REGRA ZERO).
🧪 Teste: 11 conferências e 6 mutações, todas acusadas (tests/diario-parada-esquecida.test.mjs), nos dois modos — por operador e por máquina.
✅ Não precisa do Luan: é só tela.
v2.37.672
🚚 O Histórico de Cargas agora diz PRA QUEM foi a carga, na própria linha.
📌 O que incomodava: a lista mostrava data, motorista, placa, paletes, caixas e peso —
o nome do cliente só aparecia abrindo o 👁, uma carga de cada vez. Pra responder
"o fulano já carregou?" era preciso abrir dezenas de linhas.
👤 O que mudou: entrou a coluna Cliente, entre Motorista e Placa. Carga de um
cliente só mostra o nome; carga com vários mostra os dois maiores (quem levou mais
caixa vem primeiro) e um "+N clientes" — clicar nele abre a carga com todos.
🔍 De onde sai o nome: do que já estava guardado em cada palete da carga. É
só leitura: nenhum campo novo, nada gravado, nenhuma conta refeita. Carga antiga que
não tem palete guardado continua mostrando "—" (não inventa nome).
📱 No celular a coluna vira mais um dado do cartão, com o rótulo CLIENTE em cima.
🔧 Pro Luan: nada a fazer — só o arquivo estático. Sem migration e sem API.
v2.37.671
📅 Orçamento com "2 entregas · data a definir": na hora de virar pedido, você marca a data de cada entrega.
O orçamento da FARMASI saiu pro cliente com 2 entregas de 5.000 cx e a data em
aberto (é assim que ele sai de propósito — quem marca é o cliente). Só que ao clicar
📋 Gerar caixas + pedidos a tela só perguntava a data da 1ª entrega: os dois
pedidos de 5.000 nasciam com a mesma data, e alguém tinha que caçar o segundo na
carteira pra corrigir.
Agora, embaixo da lista de caixas, aparece o bloco 📅 Data de cada entrega: uma data por
entrega, por caixa (a 1ª já vem preenchida; a 2ª em diante você marca). Cada entrega continua
virando um pedido separado — 10.000 em 2 entregas = 2 pedidos de 5.000, cada um com a sua
data, marcados 🚚 ENTREGA 1/2 e 2/2.
Se faltar uma data, o sistema avisa qual entrega de qual caixa
ficou sem e não gera nada até você preencher — nada de pedido com data chutada. O que você já
digitou não some se mudar a 1ª data. Caixa de uma entrega só, e o programa recorrente (com
intervalo em dias), continuam exatamente como eram.
v2.37.670
🚨 Importar Relatório duplicava os pedidos lançados na mão — e agora tem o 🔗 Conciliar pra arrumar o que já entrou em dobro.
📌 O que você viu: importou o relatório hoje e a carteira virou bagunça: 11 pedidos em dobro numa importação só. DEUSA 24063 (6 caixas), KININO 24010 (4 caixas) e a TCHETTO 23965, que já estava ENTREGUE com 4 registros e voltou como "programado".
🔍 Por que duplicava: pedido lançado na mão (do orçamento ou do vendedor) já vem com o nº do Sectra. Quando o relatório chega, o sistema tenta casar cada linha com o pedido manual — mas só casava quando havia UM pedido só com aquele nº + data. Um pedido do Sectra quase sempre tem várias caixas, todas lançadas no mesmo dia com a mesma data: cinco iguais, "não arrisca", e as seis linhas entravam como pedidos novos. E se a data na mão era outra (12/09 × 09/09 no Sectra), nem tentava.
✅ Agora: o casamento é pelo nº do pedido, e dentro dele caixa por caixa: mesma caixa cadastrada, mesmo código, ou mesmo número da caixa ("CX 22" × "KININO 22" — só quando o número identifica uma caixa de cada lado; o "12" da TANGARA continua sem casar). A data não é mais exigência — o relatório vence a data, como sempre foi. Cliente diferente nunca casa. Pedido já entregue ou carregado só casa pela caixa cadastrada ou pelo código exato, nunca por palpite.
🔗 Conciliar o que já entrou em dobro: em ↑ Importar Relatório → 🔗 Conciliar pedidos em dobro, o sistema lista os pares (o lançado na mão × a cópia importada), você confere, desmarca o que não for a mesma venda e confirma. O lançado na mão fica (e passa a casar com o relatório nas próximas importações); a cópia importada vai pra 🗑️ Lixeira, com o motivo escrito — dá pra restaurar por 60 dias. Cópia que já tem produção apontada não entra na lista: essa você decide na mão.
🛠 Nada foi tirado: importação sem pedido manual continua idêntica; parcelas do mesmo produto continuam separadas; a exclusão pelo ✕ continua perguntando como antes.
v2.37.669
📡 Ajuste → produção sozinha: passou de 20 caixas em 2 minutos, entra.
O dono testou na mão (04/09/2026): passou 20 caixas na frente do sensor da Slotter, em
uns 20 segundos, e o pedido ficou em ajuste. Dois motivos:
• a régua exigia 30 segundos de contagem sem parar (uma proteção contra "mão no
sensor" que acabou barrando o próprio teste) — saiu;
• o número era 10, e o esperado é 20 — virou 20.
A régua agora é a que ele descreveu: mais que 20 caixas nos últimos 2 minutos (e mais
que 20 desde o ajuste). Chapa de teste espalhada por uma hora de ajuste continua não sendo
produção, porque só conta o que passou nos últimos 2 minutos.
Lembrete: nada disso roda com o botão 🤖 O APP AGE
SOZINHO desligado no cartão da máquina no Mural — e no servidor ele está DESLIGADO na
Slotter desde as 15:25 de 04/09. A retomada da parada (mais de 20 caixas) já funcionava com
o 🤖 ligado e não mudou.
v2.37.668
📡 Com o 🤖 ligado, o sensor PREENCHE a quantidade produzida sozinho.
Pedido do dono (04/09/2026): "tem que marcar a quantidade que passar quando inicia a
produção". Até aqui o sensor só mostrava "o sensor contou N" e o operador digitava. Agora,
na máquina em que o botão 🤖 O APP AGE SOZINHO está ligado no Mural, a cada leitura do
sensor o app:
• preenche o campo Caixas produzidas do tablet (no corte e vinco, em chapas: ÷ poses);
• atualiza o parcial do pedido — o número que o fim de turno grava e que o Mural mostra
na barra "feito de";
• grava que o número veio do sensor, pra o PCP saber a origem.
Quem digita manda: se o operador corrigir o campo na mão, o sensor para de preencher
aquele pedido naquele tablet, e a dica na tela avisa. Com o campo em foco (digitando), o app
não mexe nele.
Com o 🤖 desligado nada muda: continua "só conferência". Sem
sinal do aparelho não preenche (leitura velha não é produção). Hoje só a Slotter tem o 🤖 ligado.
Vale lembrar que o sensor da Slotter já contou fantasma (12 mil num pedido de 2 mil, 02/09):
o operador ainda tem que conferir o número antes de finalizar.
v2.37.667
📡 Quando o pedido inicia, o contador do sensor entra ZERADO.
Pedido do dono (04/09/2026): "quando inicia um pedido ele entra zerado para iniciar".
Três buracos deixavam o "📡 neste pedido" nascer com número:
• Produção iniciada sozinha pelo sensor (🤖 ligado): as 10+ caixas que dispararam a
entrada já vinham contadas — o pedido abria em 11, 15, 20. Agora o zero é a leitura do
instante em que a produção entrou; o que passou no ajuste é ajuste.
• ▶ Iniciar produção num pedido que já tinha marca (rodada anterior, reinício do zero):
continuava contando do zero velho. Agora todo ▶ é um zero novo.
• A marca guardada no servidor (a que o Mural grava) valia pra sempre pelo número do
pedido: pedido rodado de novo em outro dia contava desde a primeira vez. Agora só vale a
marca desta rodada — a de antes é gravada por cima.
No Mural, com a produção já iniciada, o cartão não cai mais pra "desde o ajuste": o zero é o
do ▶. Em ajuste continua igual. O tablet e o Mural gravam o mesmo zero no servidor, então as
duas telas contam do mesmo ponto.
O que NÃO muda: pegar a máquina rodando ou adotar o pedido do
turno anterior continua contando o que já saiu (ali ninguém apertou o ▶). O apontamento do
operador continua sendo o número oficial. Nada foi apagado.
v2.37.666
📡 O "N no total" do sensor saiu do cartão do Mural.
No cartão da Máq. B Slotter (LIVRE, sensor TESTE) aparecia
"0 pç/h · 29.842 no total". Esse 29.842 era a contagem crua do contador
(ESP32) desde a última vez que o aparelho foi ligado — não é pedido, não é turno,
não é dia. Ele nunca zera de propósito (é o que segura a produção numa queda de
energia), mas na TV da fábrica só faz quem olha somar errado.
Agora esse número não aparece mais em lugar nenhum do cartão — nem na máquina
livre, nem com pedido aberto. O que continua igual: o ritmo (pç/h), o selo TESTE, o
"📡 neste pedido" (que zera a cada pedido) e o aviso de "sensor contando sem apontamento".
O contador continua sendo lido por dentro: é dele que nasce o zero de cada pedido.
Só a tela mudou. Nada foi gravado, apagado ou mexido no
aparelho nem no apontamento do operador.
v2.37.665
🧊 A caixa em 3D agora monta SEM precisar da faca em DXF.
Até aqui, só caixa com o arquivo da faca anexado virava 3D. Agora o desenho que
o próprio sistema faz a partir de comprimento × largura × altura — o mesmo
que você vê na planificação do Corte e Vinco — já serve pra montar a caixa.
No 📐 Desenho real da faca apareceu o botão 🧊 Ver em 3D. Ele só
aparece quando vai dar certo: some nas divisórias (que não têm dobra nenhuma) e
some com o arranjo de várias poses ligado (senão montaria várias caixas soltas).
O caminho do DXF continua igual: quem tem a faca
anexada monta por ela, como sempre. O que mudou é que quem não tem passou a
ter também — e é a maioria do cadastro. É o mesmo motor nos dois casos, então a
caixa sai igual.
🚨 O ✕ do Estoque PA não grudava: a caixa voltava sozinha pela produção.
📌 O que você viu: você tirou o palete que sobrou da TANGARA · 05 FLOPS 92 (pedido 23848) com o ✕ — 27/08 às 21:13 — e ele voltou quatro vezes: 31/08 08:00, 31/08 18:47, 01/09 10:45 e 02/09 06:28. A marca da sua decisão estava gravada no servidor com o seu nome o tempo todo.
🔍 Por que voltava: são quatro portas que põem caixa no Estoque PA. Em agosto (v2.37.585) a marca do ✕ passou a valer numa delas — a varredura de entrega parcelada. As outras duas de código não perguntavam nada: a que roda quando chega registro novo do operador e a que entra com o pedido no sync. Eram justamente as que trabalham todo dia. No histórico do servidor, as quatro voltas têm origem "Finalização produção" — a primeira delas.
✅ Agora: a pergunta "esse pedido foi tirado de propósito?" mora num lugar só e é feita por quem cria a linha. O que você tira com o ✕ fica tirado.
✍️ A entrada manual continua livre: quando você digita a caixa na mão, essa decisão é mais nova que o ✕ e entra normalmente.
↩️ Para desfazer um ✕ dado por engano, o caminho é o mesmo de antes: o estorno, que traz o palete de volta e apaga a marca.
🛠 Nada foi tirado: pedido sem a marca entra no estoque como sempre, e linha que já existe continua sendo atualizada pela produção — congelar a quantidade de uma linha viva seria mentir sobre o galpão.
🏷️ A logo da JP na aba do navegador — nos 32 apps e nos links do cliente.
📌 O que estava acontecendo: só 13 apps mostravam a marca na aba; os outros 19 abriam com o ícone em branco do navegador — inclusive as páginas que o cliente recebe por link (aprovação de orçamento, proposta e papel de terceiro) e os painéis de DRE, RH, Conciliação e Ponto. No sistema principal a tag do ícone estava quebrada (um PNG e um SVG grudados no mesmo endereço), então nem lá a marca aparecia direito.
🔧 Por que acontecia: o ícone era colado em código dentro de cada arquivo, um por um. App novo nascia sem — e ninguém tinha como perceber, porque falta de ícone não dá erro nenhum. É a mesma história da logo, que na v2.37.287 virou arquivo único.
✅ Como fica: o ícone virou um arquivo só (favicon.svg + apple-touch-icon.png) e os 32 apps apontam pra ele. Trocar a logo da aba passou a ser trocar um arquivo. No celular e no tablet, quem põe o app na tela de início ganha o ícone da JP no lugar do quadrado cinza.
📦 De quebra: o almoxarifado JPE usava um emoji de caixa no lugar da marca, e o aviso de “novo pedido” do painel do operador buscava o ícone num endereço de fora (github.io) — no wifi da fábrica ele saltava sem marca. Os dois agora usam a logo da casa.
🚨 A folha do pedido dizia "IPI não cadastrado" pra quem tem 15% — corrigido.
📌 O que você disse: no IPI está cadastrado; quando aparecer "não cadastrado", mostra em verde que é isento, com o cartão de isenção.
🚨 Era erro meu, e dos graves numa folha de faturamento: eu escrevia "não cadastrado" em vermelho sempre que o cadastro do cliente não trazia um % de IPI. Só que cliente sem % é o caso NORMAL — a regra da casa é que todo cliente tem 15%, e só zera quem tem carta de isenção válida. Ou seja: a folha anunciava "sem IPI" pra quem tem 15%, e o comercial podia emitir a nota sem o imposto lendo o meu papel.
✅ Como fica — quatro respostas diferentes, porque são quatro situações diferentes:
🧾 ISENTO em verde, com a validade da carta de isenção;
⚠️ isento, mas a carta vence em até 30 dias — avisa quantos dias faltam;
🔴 CARTA VENCIDA em vermelho: voltou a ter IPI e ninguém percebeu — a folha manda cobrar;
📋 com IPI: o %, dizendo se é o padrão da casa ou um valor próprio do cliente.
🔒 E não inventei conta nova: a folha passou a usar as mesmas funções que a pré-nota e o pedido já usam. Duas contas de IPI seria a nota dizer uma coisa e o papel dizer outra.
🔢 Os números do papel ganharam corpo, e a folha do pedido passou a dizer a medida da CHAPA.
📌 O que você disse: troca por uma fonte mais encorpada nos números também; e coloca as medidas da chapa, comprimento e largura.
🔢 Os números: eles estavam em Courier New, que é letra de máquina de escrever — traço fino de nascença. Passaram pra fonte da própria folha com dígito de largura fixa: têm mais que o dobro de tinta por letra e a coluna de valores continua alinhada (era só pra isso que o Courier estava ali). Vale pra quantidade, preço, total, peso, %, comissão, CNPJ, IE, CEP, datas e os números grandes do resumo.
📑 O código da caixa continua monoespaçado de propósito — ele é identificador, não número — só que agora em negrito, que imprime cheio.
📏 A medida da chapa entra na linha do item, junto da ficha da chapa: comprimento × largura em mm, na mesma ordem C × L do resto do sistema. Só a medida interna não dizia o tamanho do papel que sai da onduladeira — e é esse que a nota e o frete olham.
🧹 De quebra: quando o código da chapa já diz a onda ("ONDA B 444"), ela parou de aparecer duas vezes na mesma linha. E o azul dos títulos ficou num tom só — tinha dois diferentes no mesmo papel.
🏷️ O número da versão que aparece na tela dos apps parou de mentir.
📌 O que estava acontecendo: 10 apps mostravam v2.37.616 no cabeçalho — Qualidade, Operador, Expedição, Onduladeira, Bobinas, Escala, Motorista, Vendedor e os dois Almoxarifados. O código deles estava novo e o aviso de atualização funcionava; só o número na tela estava parado há cerca de 40 versões. Quem conferisse "qual versão está nesse tablet?" era enganado.
🔧 Por que acontecia: na hora de trocar a versão, o número da tela só era atualizado se estivesse exatamente na versão anterior. Quem perdesse uma trocada (uma subida feita na mão, um arquivo que voltou atrás num merge) nunca mais era alcançado.
✅ Como fica: os 20 números de tela do sistema estão em v2.37.660, e a troca passou a valer qualquer versão que o app estiver mostrando — não dá mais pra ficar pra trás. A conferência automática de ontem cresceu: agora ela também reprova qualquer app cujo número na tela não seja o do sistema.
📚 O histórico aqui embaixo não foi tocado: as entradas antigas continuam com o número da versão em que foram escritas — foi por causa disso que a regra antiga existia, e ela continua valendo aqui.
🔄 DRE, RH e Conciliação passaram a avisar quando sai versão nova.
📌 O que estava acontecendo: essas três telas nasceram sem o aviso de atualização que todas as outras têm. Quem deixasse a aba aberta ficava com a tela velha sem saber — e elas nem apareciam no controle de versão do sistema, então ninguém percebia.
✅ Como fica: as três mostram a versão no cabeçalho e, quando o sistema é atualizado, sobe a mesma tarja azul "Nova versão disponível — toque para atualizar" dos outros apps. Conferido nas três: avisa quando o servidor está mais novo e fica calada quando está igual.
🛡️ Pra não acontecer de novo: agora existe uma conferência automática que reprova qualquer tela nova que nasça sem esse aviso — era a terceira vez que isso escapava (encarregado e almoxarifado em maio, ponto em junho, estas três agora).
🖶️ O cinza claro do papel ganhou tinta — parou de sair borrado.
📌 O que você disse: ficou top, mas onde é cinza claro não dá pra visualizar, está saindo meio borrado na impressão.
🔍 O defeito era meu, e eram duas coisas juntas: eu tinha texto de 6,2 pt num cinza de tela (#94a3b8). No monitor esse tom retroilumina e se lê; no papel, uma letra desse tamanho nesse tom não tem tinta suficiente pra formar o desenho da letra — vira borrão. Adiantava pouco corrigir só uma das duas.
✅ Como fica: os cinzas escureceram dois tons (rótulos, notas e observações) e nada no papel fica abaixo de 7 pt — a folha do pedido subiu mais, porque ela sobrava meia página em branco. Continua cinza (segue sendo informação secundária), só que agora com tinta.
🔄 Vale pra TODO documento impresso do sistema: o cabeçalho e o rodapé são compartilhados (romaneio, laudo, orçamento, ordem de compra, ficha…) e também escureceram. Mexi só na cor — nenhum documento mudou de layout.
📏 Na lista de pedidos, a coluna do vendedor foi de 11 % pra 13 %: com a letra maior, "ARMANDO BARROS SILVA JUNIOR" quebrava em três linhas.
📦 O painel de carregamento passou a dizer QUAL CLIENTE está subindo no caminhão.
📌 O que você disse: "eu quero saber qual cliente está sendo carregado". A linha mostrava a placa, o expedidor, o motorista, os paletes e as caixas — tudo menos o que está indo no baú.
✅ Como fica: embaixo da placa aparece 📦 TANGARA. Se o caminhão levar mais de um cliente, cada um vem com as suas caixas — TANGARA 1.402 cx · FK GRUPO 1.200 cx · KININO 300 cx — do maior pro menor, até três nomes e o resto como "+2", pra não estourar a linha.
✅ Nas cargas fechadas também: antes o nome do cliente só aparecia quando faltava o romaneio ("falta o romaneio de TCHETTO") — a carga já concluída não dizia de quem era. Agora diz.
ℹ️ Vale para os dois jeitos de carregar: o da escala/avulso e o do plano de carga.
⚠️ Caminhão em que ninguém bipou nada ainda continua sem nome nenhum, em vez de um traço que parece cadastro faltando.
🧾 Dá pra imprimir o pedido do vendedor — e mandar pro comercial faturar sem redigitar nada.
📌 O que você disse: essa é a tela da solicitação, e você precisa imprimir o pedido pra mandar pro comercial no Sectra fazer o faturamento — com data, preço, comissão do vendedor, tudo. Até agora o pedido só existia no cartão da tela: pra faturar, alguém redigitava lendo o monitor.
✅ Como fica — são dois papéis, de propósito:
🧾 "Imprimir pro faturamento", um botão em cada pedido: uma folha do pedido com a razão social, CNPJ, IE, endereço e CEP do cadastro (não só o apelido), condição de pagamento, prazo e IPI, os itens com quantidade, preço unitário de 3 casas, total e peso, a comissão do vendedor (valor, % e sobre quanto) e uma linha no pé pra anotar quem faturou, quando e o nº da nota.
🖨️ "Imprimir / PDF", no topo da lista: a lista inteira numa folha deitada, uma linha por caixa, com comissão por linha e um resumo por vendedor no fim.
🔒 As duas levam comissão, então as duas são marcadas: tarja de USO INTERNO no topo, "não enviar ao cliente", e INTERNO_ no começo do nome do arquivo — que é o que aparece antes de alguém anexar num WhatsApp.
🔸 O que a folha não deixa passar: pedido recusado aparece em cinza e fica fora dos totais (não virou faturamento); cliente sem CNPJ no cadastro sai com aviso vermelho em vez de espaço em branco; e comissão sem vendedor vinculado diz o porquê do traço. A conta da comissão é a mesma de sempre (% do cadastro do cliente, só com vendedor vinculado) — nenhuma conta nova.
📄 Nas duas, a janela de impressão tem "Salvar como PDF".
🤖 "Fluxo contínuo" passou a ser medido por tempo — o sensor manda com delay de 10 segundos.
📌 O que você disse: o delay de 10 s no aparelho é de propósito. Com ele, a regra "4 leituras seguidas subindo" (v650) nunca fechava: entre um envio e outro o app via leitura vazia e a sequência quebrava — o ajuste só virava produção pelo ▶ do operador.
✅ Como fica: ajuste vira produção sozinho com mais de 10 caixas nos últimos 2 minutos e pelo menos 30 segundos de contagem sem parar, onde "sem parar" é nenhum buraco maior que 15 segundos entre uma contagem e a próxima (o delay de 10 s com folga). Mão no sensor de vez em quando abre buraco maior e continua ajuste. O ▶ do operador segue sendo o caminho normal.
🏢 Razão social e nome fantasia são duas coisas, e agora cada uma está no seu lugar.
📌 Nos 59 clientes trazidos do Sectra: a razão social é a da Receita, e o nome fantasia só tem fantasia de verdade. 22 têm fantasia (PAPER BOX, SILK GRAF, BALAS TOFFANO, SALINAS EMBALAGEM…). As outras 36 não têm fantasia registrada em lugar nenhum — nem na Receita, nem no Sectra — e nessas o nome ficou com a razão social inteira, como você pediu, em vez de um pedaço dela.
🗂️ A fantasia virou campo próprio no cadastro, então dá pra saber quando a empresa tem uma e quando simplesmente não tem.
ℹ️ Embaixo do campo Razão social agora está escrito que é a da Receita e que é ela que vai na nota.
⚠️ Ninguém ficou órfão: os pedidos e as caixas continuam todos ligados aos seus clientes, e nenhum nome ficou repetido.
📡 A barra do sensor não depende mais do tablet: o Mural grava sozinho o zero do pedido.
📌 O que aconteceu: o 19403 rodou a noite inteira com "0 de 2.000" e o sensor contando. A marca de zero do pedido só nascia no tablet do operador — e o tablet do Arnaldo não falou com o servidor a noite inteira. O Mural via tudo e não tinha onde escrever.
✅ Como fica: quando o Mural vê pedido RODANDO, sensor no ar e nenhuma marca, ele grava a marca no servidor (o total do sensor naquele instante), uma vez por pedido. A partir dali a barra e o "neste pedido" contam. O tablet, quando voltar, adota a mesma marca em vez de inventar outra — as duas telas contam do mesmo zero.
✅ Monitoramento de hoje à noite (21:55–21:59): com a Slotter parada, o total do sensor ficou em 12.383 por 4 minutos, sem mexer. Parado, ele não conta fantasma hoje.
⚠️ A marca vale "a partir de agora": as caixas que passaram antes dela ficam só no apontamento do operador.
🏢 Razão social como está na Receita, e o nome do cliente é a fantasia.
📌 O que mudou no cadastro: os 59 clientes trazidos do Sectra tiveram a razão social conferida na Receita — 33 mudaram, e 12 ganharam o nome de fantasia (a MIUCHA virou STILLOS EMBALAGENS, a TOFFANO virou BALAS TOFFANO). A razão que o Sectra usa continua guardada no cadastro, só que num campo à parte.
⚠️ Por que precisou disso: a razão do Sectra quase nunca é igual à da Receita ("MIUCHA LOPES FELIPE EMBALAGENS - ME" × "MIUCHA LOPES FELIPE"). Era por ela que o relatório importado achava o cliente. Trocando sem guardar a antiga, todo pedido importado deixaria de achar o cadastro e nasceria um cliente repetido — calado, no dia seguinte.
🔧 E um erro antigo apareceu no caminho: quando dois CNPJs da mesma família estão cadastrados, o apelido curto ("ART CAIXAS") podia ganhar da razão social exata e jogar o pedido no cliente errado, com a nota saindo no CNPJ errado. Agora a razão social decide primeiro; o apelido só entra se ela não achar ninguém.
🔗 Regra do dono, de hoje: CNPJ diferente = cadastro próprio. As junções de ELIEL e VIVA foram desfeitas, tudo voltou pro lugar (a VIVA GRÁFICA recebeu de volta o pedido e as 3 caixas) e o ART CAIXAS não foi juntado.
🔄 Operador em DUAS máquinas: sai do pedido só pra ir pra outra máquina — e o pedido daqui continua rodando.
📌 O que você pediu (02/09): "não deixa sair, a não ser que eu vá iniciar outra caixa em outra máquina". O cadastro do operador já tinha as máquinas dele (Cadastros → Operadores) e o app já mostrava as abas de máquina na lista; faltava a porta de dentro do pedido.
✅ Na tela "Cada pedido é uma vida só" aparece, só pra quem tem mais de uma máquina no cadastro, o botão 🔄 Ir pra <outra máquina> · este pedido continua rodando. Toca, cai na lista da outra máquina e abre a caixa de lá. O pedido daqui não pausa nem grava: continua RODANDO no Mural, e ele volta pra ele pela aba quando quiser.
✅ Consertado de passagem (era um defeito antigo das abas): no fim de turno de quem opera duas máquinas, o parcial da Slotter podia sair carimbado "Corte e Vinco" — a máquina do registro era a da TELA, não a do pedido. Agora cada progresso guarda a máquina em que foi aberto e é ela que vai no registro.
⚠️ O sensor só age no pedido da máquina em que a tela está: o da outra máquina não ganha parada nem retomada automática enquanto o operador estiver do outro lado.
📦 "Cada pedido é uma vida": com o sensor ligado, o operador não sai do pedido sem dar OK — e o OK já vem com o número do sensor pra ele conferir.
📌 O que você pediu (02/09): contador zerado a cada pedido (já era a marca); não deixar sair do pedido em produção sem dar OK; o OK finaliza com a quantidade contada e reprograma o resto; e o operador confere antes de gravar.
✅ ↩ Voltar e ⏸ Pausar com a produção aberta abrem a tela "Cada pedido é uma vida só": o campo já vem com o que o sensor contou neste pedido (no corte e vinco, em chapas), o operador confere ou corrige e toca OK. O app grava a produção no nome dele e, se sobrou material, manda o resto pro PCP como Reprogramado (a mesma coisa que o botão "reprogramar" fazia antes da v2.37.1). Ou "Ficar no pedido". Não tem "pausar" ali.
✅ ✅ Finalizar com o campo vazio: preenche com o número do sensor e para — o operador confere e toca de novo. O número do sensor nunca entra sem passar por ele.
✅ Ajuste → produção só com FLUXO CONTÍNUO: você lembrou que no ajuste o operador passa a mão no sensor e isso conta caixa. Agora, além das 10 caixas em 2 minutos, precisa de 4 leituras seguidas do aparelho com o número subindo (uns 20 segundos de caixa passando sem parar). Rajada solta com pausa no meio continua ajuste. O ▶ do operador continua sendo o caminho normal; o automático é só pra quando ele esquecer.
⚠️ Tudo isso só na máquina com o 🤖 ligado no Mural. Nas outras, Voltar, Pausar e Finalizar continuam exatamente como eram. Fim de turno e troca de turno não mudaram.
🤖 O "app age sozinho" ficou como você detalhou: 10 caixas em curto período entram em produção, e só 20 caixas retomam uma parada.
✅ Ajuste → produção: mais de 10 caixas nos últimos 2 minutos. Antes contava desde o começo do ajuste, e 10 chapas de teste espalhadas numa hora de ajuste virariam produção. Uma caixa de vez em quando continua sendo ajuste.
✅ Parada → produção: com a parada aberta, mais de 20 caixas (era 5) encerram a parada e retomam sozinho. A pergunta de motivo sem resposta também só é recolhida com 20.
✅ Parada de 60 s: igual — avisa e abre a lista de motivos. Tudo isso só na máquina com o botão 🤖 ligado no Mural.
🔗 ELIEL e VIVA juntados — e a importação do Sectra agora sabe disso.
📌 O que foi feito no cadastro: ELIEL FRANCÃO foi juntado no ELIEL EMBALAGENS (fica o CNPJ 42.170.768) e VIVA GRÁFICA foi juntada no VIVA PRINT (fica o CNPJ 49.635.314, e o pedido 23770 mais as caixas 1, 5 e 10 LITROS passaram pra ele).
⚠️ Por que precisou mexer no código: esses clientes têm dois CNPJs e o Sectra fatura pelo outro. Sem aviso, o próximo relatório importado chegaria com uma razão social que não bate com cadastro nenhum e o sistema criaria o cadastro repetido de volta — desfazendo a junção sozinho, calado. Agora "ELIEL FRANCAO - ME" e "VIVA INDUSTRIA GRAFICA LTDA- ME" apontam pro cadastro que ficou.
🚫 O VIVA PACK NÃO foi juntado, de propósito: apesar do nome, a razão social dele é BOOKPRINT GRÁFICA E EDITORA, fica em Guarulhos e a sócia é outra pessoa. É outra empresa, e continua com cadastro próprio.
⚠️ Nada foi apagado sem cópia: os dois cadastros que sumiram estão guardados em backup, e o que ficou traz na observação com quem foi juntado, quando e por quê.
📡 O cartão do Mural voltou a mostrar o total do sensor — como era antes de hoje.
📌 O que você disse: "deixa como já estava, que estava funcionando — era só para acrescentar o app agir sozinho". A v2.37.641 tinha escondido o "N no total" em todo pedido, e num pedido sem a marca do sensor (o 19403 de hoje) o cartão ficava sem número nenhum.
✅ Como fica: igual à regra de antes (v2.37.491): quando existe a linha "📡 neste pedido", o total do aparelho some; quando não existe, ele aparece ao lado do ritmo. Nada mais mudou — os dois botões (mostrar pelo sensor / o app age sozinho), o "age sozinho" desligado por padrão e a marca que se refaz sozinha (v646) continuam.
📡 "O sensor funciona mas não marca as caixas" — a marca de zero do pedido agora se refaz sozinha.
📌 O que aconteceu: o pedido 19403 (Arnaldo, Slotter) estava rodando há 2h29 com o sensor contando 830 pç/h e o cartão dizendo "0 de 2.000". Conferido no servidor: o pedido não tinha a marca de zero do sensor. E os três pedidos anteriores tinham a marca em 48.378 — o total congelado do aparelho antes de ele ser regravado hoje (o total recomeçou e está em 11.532). Marca maior que o total = conta recusada pra sempre.
✅ Como fica: a marca deixou de ser "uma vez só, no ▶". Com o pedido aberto, o app do operador confere a cada 15 s e, se a marca falta, o aparelho reiniciou (total menor que a marca) ou a chave do sensor mudou (TESTE_ ↔ real), carimba "conta a partir de agora" — guardando junto o que o operador já tinha declarado, pra os dois números continuarem comparáveis. O operador vê o aviso na tela. Vale no ajuste também.
⚠️ Só com o aparelho no ar: leitura velha não vira zero. E marca boa fica intacta — nada é regravado à toa.
📋 No 19403 de hoje: assim que o tablet do Arnaldo atualizar, o cartão passa a mostrar "neste pedido" contando dali em diante — as caixas de antes desse momento ficam só no apontamento dele, porque não há marca que diga onde elas começaram.
📡 O cartão da máquina no Mural ganhou DOIS botões — um pra mostrar pelo sensor, outro pra o app agir sozinho.
📌 O que você pediu (02/09): a Slotter continua "ao vivo" na tela, mas o app não pode agir sozinho ainda. Na v2.37.643 as duas coisas estavam no mesmo botão.
✅ 📡 MOSTRANDO PELO SENSOR / mostrando pelo apontamento: só a tela do Mural — a barra "0 de 2.000 cx" e o ritmo do cartão. Não muda nada no app do operador nem no registro. É o que a Slotter tem ligado hoje, e ficou como estava.
✅ 🤖 O APP AGE SOZINHO / o app não age sozinho: só este liga as três regras no app do operador daquela máquina (ajuste >10 caixas entra em produção, parada de 60 s pede o motivo, >5 caixas retoma). Nasce desligado em todas as máquinas, inclusive na Slotter. Ao ligar, o Mural pergunta antes e lembra de medir o sensor com a máquina parada.
✅ O que não muda em nenhum dos dois: o registro do pedido continua sendo o que o operador aponta, e a dica "o sensor contou N" continua aparecendo pra conferência.
🛣️ O km pela rota agora lê o número da casa de dentro da linha do endereço.
📌 O que faltava: em 🏢 Dados da Empresa o endereço é uma linha só ("Rua Aparecido Durvalino Simpioni, 900, Jardim Paraíso"), e o cálculo da v2.37.642 só usava o número quando ele vinha em campo separado — a fábrica era achada "na rua", não no portão.
✅ Agora ele entende "Rua X, 900, Bairro", "Rua X, 900 - Bairro" e "Rua X 900", e o número entra na busca. Vale pra fábrica e pro campo de endereço antigo do cliente. Rua com hífen no nome não é cortada.
🧪 Frisokar (FK GRUPO) refeita: com a fábrica no endereço certo deu 19 km · 24 min (antes 15 km, partindo do centro de Boracéia). Atualizado no cadastro. Junto, o endereço da empresa foi corrigido pra Simpioni (era "Simpione", que o mapa não achava) e o CEP 17270-000 preenchido.
📡 As ações do sensor ficam PRONTAS, mas DESLIGADAS — quem liga é o botão do Mural, máquina por máquina.
📌 O que você pediu (02/09): "deixa tudo pronto pra quando for configurar, mas o apontamento fica do jeito que está — a contagem não pode ser pelo sensor ainda".
✅ Como fica: as três regras da v2.37.641 (ajuste >10 caixas entra em produção, parada de 60 s pede o motivo, >5 caixas retoma) só funcionam na máquina em que o botão "📡 AO VIVO PELO SENSOR" do cartão do Mural estiver ligado. No padrão ("👤 lendo pelo apontamento") o app do operador só mostra o número do sensor pra conferência, como desde a v2.37.485, e não aperta botão nenhum. O botão agora diz isso no próprio texto.
⚠️ A Slotter está com o botão LIGADO hoje (é o "AO VIVO PELO SENSOR" que aparece no seu print). Pra deixar a contagem pelo apontamento, toque nele uma vez — ele vira "lendo pelo apontamento" e a barra do cartão volta a ser o que o operador aponta.
📋 Pra instalar nas outras máquinas: ficha do ESP32 (endereço, corpo da mensagem, a chave de cada máquina e onde está o token) em cartonagem2-docs/FICHA_ESP32_sensor_maquinas.md, no seu Mac.
🛣️ O km da fábrica até o cliente agora nasce sozinho do endereço — pela estrada, não em linha reta.
📌 O que você pediu: o campo "Distância da fábrica (km)" existia desde a v2.37.364, mas era digitado à mão e quase nenhum cliente tinha — e sem ele a escala não estima hora de chegada, o orçamento não calcula frete e a doca não prevê o caminhão.
✅ Como ficou: no cadastro do cliente, ao lado do km, tem o botão 📍 Calcular pela rota. E quando o endereço entra (pela Receita, no 🔍 do CNPJ, ou digitado) e o km está vazio, ele calcula sozinho. O mapa é o OpenStreetMap e a rota de carro é do OSRM — sem chave, sem custo.
🔍 Ele diz de onde veio o número: embaixo do campo aparece "≈ 15,3 km pela estrada · 17 min de carro (Boracéia → Bariri) · ponto na rua". Se só achou o CEP ou o centro da cidade, avisa — quando o ponto é o centro da cidade, pode errar alguns km, e a frase fala isso em amarelo. Se não achar o endereço no mapa, não inventa: deixa vazio e explica.
✋ Km digitado à mão manda: o cálculo automático só preenche campo vazio. Quer trocar pelo da rota, é o botão.
🧪 Teste com a Frisokar (FK GRUPO, Bariri): deu 15 km · 17 min, já gravado no cadastro. A rota achou a rua do cliente mas a fábrica só pela cidade — preencha o CEP em 🏢 Dados da Empresa (17270-000) que a precisão melhora pra todo mundo.
📡 O sensor da máquina agora AGE — três regras suas, e o total zera a cada pedido.
📌 O que você pediu (02/09): o total do sensor apagado em todo pedido novo; em AJUSTE, passou de 10 caixas entra em produção sozinho; máquina parada mais de 60 segundos, o app pede pra justificar; e se passar de 5 caixas, volta pra produção sozinho.
✅ Total zerado por pedido (Mural): o "11.334 no total" do aparelho não aparece mais em pedido nenhum — com apontamento aberto o cartão mostra só "neste pedido", contando do zero desde o momento em que o operador pegou o pedido (o 🔧 Ajuste). O total de vida do aparelho só volta no cartão de máquina LIVRE, onde é o único número que existe.
✅ Ajuste → produção sozinha (app do operador): com o pedido em 🔧 Ajuste, se o sensor contar mais de 10 caixas, o app aperta o ▶ por conta própria, avisa na tela ("Produção iniciada SOZINHA: o sensor contou 11 caixas no ajuste") e essas caixas entram na conta do pedido. Se o operador já estiver no ▶ (a pergunta da perda do ajuste ou a paletização na tela), o app espera ele terminar.
✅ Parada de 1 minuto → pede o motivo: o aviso amarelo continua, mas agora a lista de motivos abre sozinha, uma vez por parada. E a parada registrada começa na hora em que a máquina parou de verdade (o sensor viu), não na hora em que o operador respondeu. Com a parada já registrada o aviso para de cobrar "registrar parada" (antes cobrava mesmo assim).
✅ Passou de 5 caixas → retoma sozinha: com a parada aberta, se o sensor contar mais de 5 caixas, o app aperta o ▶ Retomar por conta própria e a linha da parada fica marcada "retomada pelo sensor". Se a lista de motivos abriu e ninguém respondeu, ela é recolhida — nenhuma parada é gravada sem motivo.
⚠️ Só com o aparelho no ar e com marca: sem sinal do sensor, pedido pego antes desta versão ou máquina sem sensor, o app fica exatamente como era. Os números (10 / 60 s / 5) moram num lugar só (js/61). Atenção: um sensor que conta fantasma (medido em 21/08: ~97/min com a máquina parada) vai iniciar e retomar produção à toa — essas regras só valem com o sensor contando caixa de verdade.
⛔ O botão de inativo chegou à ficha do Micro / Cartão.
📌 Na v2.37.639 a tabela de Micro / Cartão já tinha o ⛔ na linha, mas a ficha (o cadastro aberto) não tinha o campo. Agora tem os dois, iguais aos da caixa: o campo 🚦 Situação na seção 4 e o botão ⛔ Deixar inativo no rodapé (que vira 🟢 Reativar).
✅ A regra é a mesma: inativo some só da lista de escolher; pedido, palete, etiqueta e histórico continuam iguais. Cada inativar/reativar fica no histórico do item.
⛔ A caixa agora pode ficar INATIVA — em vez de ser excluída.
📌 O que aconteceu: você tentou excluir a caixa 10 MOLHO 150ML (TCHETTO) e o sistema barrou: ela está num pedido já entregue. Excluir deixaria o pedido sem cadastro de caixa — mas até ontem não havia outra saída, e a caixa continuava aparecendo pro vendedor e na lista do pedido.
✅ Onde está: Cadastros → Caixas. Na linha da caixa tem o botão ⛔ (deixar inativa); dentro do cadastro tem o campo 🚦 Situação e o botão ⛔ Deixar inativa no rodapé. E o próprio aviso de "não pode ser excluída" agora oferece inativar na hora. O mesmo vale pra tela de Micro / Cartão.
✅ O que a inativa faz: some da lista de escolher — não entra em pedido novo no PCP, não aparece no orçamento, no app do vendedor nem no desenvolvimento. Se alguém digitar o código dela no orçamento, a tela avisa em vermelho.
✅ O que ela NÃO faz: não apaga nada. Os pedidos, paletes, etiquetas, faturamento e histórico da caixa continuam iguais, e o pedido que já tem a caixa continua mostrando ela (marcada "— INATIVA"). Na tela de Caixas ela fica apagada, com o selo 🔴 INATIVA, no fim da lista do cliente — e tem o ✓ ocultar inativas. No relatório impresso sai "(INATIVA)" do lado do código.
🔄 Pra voltar: o mesmo botão vira 🟢 Reativar. Cada inativar/reativar fica no histórico da caixa, com quem fez e quando.
🏢 CNPJ repetido não cadastra mais — e os clientes ganharam a Inscrição Estadual que estava no Sectra.
📌 O que aconteceu: ALPACK e "ALPACK - PRODUTOS ADESIVOS" estavam com o mesmo CNPJ 06.997.077/0001-64 — e não eram os únicos: DCX × "DCX PACKAGING DESIGN EMBALAGENS" e FK GRUPO × FRISOKAR também. Três pares da mesma empresa cadastrada duas vezes, cada um dividindo pedido, comissão e crédito sem ninguém perceber.
✅ Agora a tela barra. Ao salvar um cliente com CNPJ que já é de outro, ela não grava e diz qual é o cliente que já tem esse CNPJ. O aviso aparece embaixo do campo enquanto você digita, e um cadastro que já é repetido abre avisando. Compara só os números — com ou sem pontinhos dá igual.
📱 No app do vendedor também: "cliente novo" com CNPJ que já existe não passa — manda escolher o cliente já cadastrado. Era por essa porta que nascia o repetido.
⚠️ Nada foi apagado: os três pares continuam como estão. Fundir é o 🔗 Juntar repetidos, quando você decidir. Editar um cadastro que já tem o CNPJ repetido continua funcionando — a trava é só pra não nascer mais um.
📥 Do Sectra pra cá: 64 dos nossos 95 clientes casaram pelo CNPJ com o cadastro do Sectra. Entraram 47 Inscrições Estaduais, 41 nomes de contato, 36 e-mails, 5 telefones e o endereço da VIVA GRÁFICA — só em campo que estava vazio; nada do que já estava digitado aqui mudou. Cópia de antes em ~/backups-jp/clientes-antes-sectra-2026-09-02.json.
🔗 Amarrados a pedido seu: BELMONT = VINAGRE BELMONT S/A (44.806.784/0001-15) e Marilei = MARILEI CRISTINA ANDREUSSI BERNAL (33.765.650/0001-87) — os dois ganharam CNPJ, IE, razão social e endereço do Sectra. ⚠️ O CNPJ da Marilei é o mesmo do TRANS BERNAL: virou o 4º par repetido, pra fundir no 🔗 Juntar repetidos quando quiser.
🔢 O tamanho do Sectra: 719 empresas-cliente (por CNPJ), 515 que já compraram alguma vez, 139 com compra desde 2024 e 101 desde 2025. Dessas, 658 ainda não estão aqui — inclui as cartonagens que compram chapa (Salinas, Circulus, Fraspaper…), que são cliente do outro negócio.
🛒 Pedido de Compra: agora dá pra editar, imprimir, salvar em PDF e mandar pelo WhatsApp — e o comprador vê o que está comprando, com o preço cadastrado e o link de compra.
✏️ Editar: em "Meus pedidos" cada pedido ganhou o botão ✏️ Editar. Os itens voltam pra lista, você mexe e clica em 💾 Salvar alterações: o pedido é trocado no lugar (mesmo número, mesma posição) e o que era antes fica guardado no histórico dele — nada some. Só enquanto está ⏳ com o comprador; depois que ele pegou, preço, fornecedor e data são editados no app de Compras (o botão explica isso). Se ele pegar o pedido no exato momento em que você salva, o sistema não grava por cima e avisa.
🖨️ Imprimir / 📄 Salvar PDF / 📱 WhatsApp: três botões por pedido. O papel sai com a logo, o número da OC, fornecedor, urgência, os itens com quantidade, preço cadastrado, total de referência, o valor que o comprador fechou (e quantos % acima ou abaixo do cadastrado) e os links de compra. No celular o PDF abre o compartilhar; no computador baixa o arquivo e abre o WhatsApp já com o texto do pedido, é só anexar.
💰 Vai com o preço cadastrado no sistema. Ao escolher o produto, a tela já diz "preço cadastrado R$ X/kg → 20 kg = R$ Y" (produto sem preço no almoxarifado avisa). Cada item do pedido leva a quantidade de verdade, a unidade, o preço cadastrado e a categoria — e o total de referência vai junto.
🔗 Link de compra na internet: campo novo, opcional, por item. No app de Compras vira o botão 🔗 Comprar no link (abre em aba nova). Link que não começa com http(s) não vai.
📱 No app de Compras o comprador passou a ver, item por item: quantidade com a unidade certa (era "100 kg un"), a cor da tinta, o preço cadastrado e quanto dá, quanto tinha no estoque na hora do pedido e o link. O card mostra 💰 ref. sistema R$ Y, e ao clicar em Gerar OC o campo Valor já vem preenchido com essa referência (ele muda se negociou outro). O PDF e a mensagem do WhatsApp que ele manda pro fornecedor também levam a coluna do preço de referência e os links.
📦 No Lançamento de Insumos nasceu a caixa 🛒 Compras em andamento: todo pedido que você mandou pro comprador e ainda não chegou fica ali à vista, com o status dele. Quando o material chegar, 📦 Chegou — dar entrada marca o pedido como recebido (o app de Compras vê a mesma coisa, é um status só) e abre a baixa com uma linha por item: produto, quantidade, preço cadastrado, categoria certa e a soma no estoque do almoxarifado. Antes o pedido só aparecia se o comprador lembrasse de marcar "recebida" — e entrava numa linha só, como manutenção, mesmo sendo tinta.
✅ Conferência do preço: o valor que o comprador fechou vira o total da nota e os itens entram pelo preço cadastrado — a caixa amarela diz "comprador fechou R$ X · +5% do cadastrado" e a lista faz a conferência de sempre (✅ bate / ⚠ passou / ⚠ faltam). Cada linha ganhou um ✏️ pra corrigir o valor pelo que veio na nota, sem tirar e pôr de novo.
🔧 De quebra: valor digitado no app de Compras com vírgula ("250,00") era lido como "sem valor" na baixa — agora lê certo. Pedido antigo (feito antes desta versão) continua entrando do jeito de antes.
🖨 O botão de imprimir etiqueta agora PERGUNTA antes — e quando você manda continuar no lote, ele continua de verdade.
📌 O que aconteceu: hoje, no KININO 06 (pedido 24010), você encostou sem querer no 🖨 Imprimir prontos e continuar. Num toque só saíram 2 etiquetas, o lote 1 fechou e nasceu um registro de 2 paletes · 1.402 cx no histórico. Depois o app perguntou se você queria continuar no lote 1, você respondeu continuar — e mesmo assim as 15.226 cx da noite foram pro lote 2, num segundo registro.
✅ Agora ele pergunta antes de imprimir. Aparece uma caixa dizendo quantas etiquetas vão sair e quantas caixas, que o lote FECHA ali, e que o que você produzir depois vai pro lote seguinte — em registro separado, que não se apaga. Dois botões: 🖨 Imprimir o lote N ou Não, continuar produzindo. Encostar sem querer não fecha mais nada.
✅ E o "continuar" continua de verdade. O motivo de ele não continuar era que o app levava até 2 minutos pra saber que ele mesmo tinha acabado de imprimir — nesse tempo ele perguntava "o lote 1 ficou sem etiqueta, continua nele?" sobre um lote que já tinha saído impresso. Agora a etiqueta impressa vale na hora, e essa pergunta errada não aparece mais.
🔔 E se um dia não der mesmo pra continuar (o PCP imprimir aquele lote enquanto você produz), o app avisa na tela: "o lote N saiu impresso — o que você produzir agora vai pro lote N+1". Antes ele trocava de lote calado.
⚠️ Nada foi apagado: os dois registros do KININO 06 continuam no histórico do jeito que aconteceram.
🖨 A tela de Caixas ganhou relatório: imprime o que está na tela e gera PDF pra enviar.
📌 Onde está: Cadastros → Caixas. No lugar do botão 📄 Importar ficha (PDF/XLS) agora têm três, e o nome de cada um diz o que ele faz:
🖨 Imprimir relatório — versão interna, no papel.
📄 PDF interno (amarelo) — completo, com comissão e limite de crédito.
🤝 PDF pro cliente (verde) — sem os dois. É esse que você manda pra fora.
✅ O que sai na folha: exatamente as caixas que estão na tela — se você filtrou por cliente ou digitou na busca, sai o filtrado; sem filtro, sai tudo. Nesta ordem: ficha do cliente (razão social, CNPJ, I.E., endereço completo, contato, telefone, WhatsApp, e-mail, vendedor, condição de pagamento, prazo, IPI) · a tabela das caixas com as mesmas colunas da tela · o resumo (peso médio, preço médio, preço médio por quilo e a faixa do menor ao maior R$/kg) · e as compras: os pedidos dessas caixas, com quantidade, valor, peso e o total.
📱 Pra enviar: no celular os dois PDFs abrem o compartilhar (WhatsApp, e-mail); no PC eles baixam o arquivo. O Imprimir relatório abre a janela de impressão — e ali também dá pra escolher "Salvar como PDF".
🛑 O PDF pro cliente só sai com UM cliente escolhido no filtro. Sem filtro, a folha iria com as caixas e os preços de vários clientes juntos — mandar isso pro cliente A entrega a tabela do cliente B, e não tem como desfazer. Se você clicar sem filtrar, ele avisa e não gera nada. O PDF interno e o Imprimir continuam saindo com quantos clientes você quiser — nesse caso a coluna Cliente entra na tabela.
⚠️ Dá pra saber qual PDF está na sua mão antes de mandar, por três sinais: (1) o interno tem uma tarja amarela no alto de TODA folha — "USO INTERNO · não enviar ao cliente"; (2) o arquivo dele começa com INTERNO_ no nome, e o do cliente não; (3) o rodapé do interno diz "documento interno".
🔒 No PDF do cliente a comissão não é escondida — ela não é escrita. Não adianta copiar o texto do PDF ou abrir em outro programa: ela não está lá. Conferido abrindo o arquivo gerado e lendo o texto de dentro dele. O que muda de rótulo: onde o interno diz "Faturamento", o do cliente diz "Total comprado".
💰 De onde saem os números: "~" antes do preço = valor calculado pelo sistema, ainda não digitado no cadastro. Valor/kg = preço unitário ÷ peso da caixa. Nas compras, pedido já faturado conta a quantidade da baixa; os outros contam a quantidade do pedido — valor sempre sem IPI, a mesma conta do painel de custos. Comissão (só no interno) = % do cadastro do cliente, e só de cliente com vendedor vinculado.
📦 O Importar ficha não foi apagado — o botão saiu da tela a seu pedido, mas o código continua inteiro. Pedindo, ele volta pro lugar em um minuto.
🔧 Pro Luan: nada.
🛟 Uma rede embaixo do conserto do registro repetido — agora no servidor.
📌 Por que ainda precisava: a v2.37.632 fechou a porta no app do operador, mas
tablet com a versão velha guardada continua mandando a cópia até atualizar. E a limpeza
automática que o sistema já tinha nunca enxergou esse par: ela compara os horários, e a cópia
não tem nenhum.
🕶 O que a rede faz: quando chega um "parcial de fim de turno" sem nada dentro
— sem chegada, sem ajuste, sem início, sem palete e sem parada — e já existe no pedido um
registro completo do mesmo operador, mesma etapa, mesmo dia e mesma quantidade, o servidor
reconhece a cópia.
🗂 Ela MARCA, não joga fora: a cópia entra já anulada, com o motivo escrito
na tarja. Fica fora de todas as contas, o rastro continua legível no histórico do pedido e dá
pra desfazer — e ainda serve de aviso de que algum tablet está atrasado.
⚠️ Erra sempre pro lado de deixar passar: basta UM sinal de vida no registro (um horário,
um palete, uma parada) e ele entra inteiro. Produção de verdade não pode ser barrada por uma
trava de duplicata — número a mais se audita, apontamento perdido não volta.
🔧 Pro Luan: só reiniciar a API (pm2 restart all). Não tem
migration — nada muda no banco.
🔐 "The quota has been exceeded." não barra mais a entrada no sistema.
👀 O que aparecia: usuário e senha preenchidos, botão Entrar, e uma tarja vermelha com uma frase em inglês que não diz o que fazer. Tentava de novo, mesma coisa. Parecia senha errada ou internet caída — não era nem uma coisa nem outra.
🔍 Por que acontecia: essa frase é do navegador, não do sistema: é o Safari dizendo que o armazenamento daquele aparelho está cheio. O servidor tinha conferido a senha e já tinha liberado o crachá — só que, na hora de guardar a sessão no navegador, o aparelho recusou, e essa recusa era lida como "erro ao entrar". A pessoa ficava do lado de fora com o acesso já aprovado. Pior: o crachá recém-liberado nem chegava a ser guardado, então cada nova tentativa gastava outra sessão à toa.
✅ Agora: o navegador recusar guardar não segura mais o login. Você entra e trabalha normalmente. Se o aparelho estiver cheio, a tela avisa em português o que está acontecendo e oferece o botão 🧹 Liberar espaço agora, que apaga só a cópia local (pedidos, caixas, cadastros) — tudo volta do servidor no carregamento seguinte.
🛟 De brinde: o aparelho cheio também deixou de se deslogar sozinho a cada F5, e o botão Sair parou de poder travar pelo mesmo motivo.
⚠️ Antes de limpar: o botão pergunta primeiro. Ele apaga a cópia guardada neste navegador — o servidor não é tocado. Se você tem alguma edição feita nesse aparelho que nunca chegou no servidor, ela se perde.
📍 Terceira vez da mesma família: já tinha zerado a carteira num Mac (v2.37.360) e travado o cadastro de caixas (v2.37.586). A regra que vale pro sistema inteiro: guardar cópia local nunca pode ficar no caminho do que a pessoa precisa fazer.
🔧 Pro Luan: nada.
🔁 O mesmo trabalho não é mais lançado duas vezes no histórico do pedido.
👀 O que aparecia: dois registros iguais — mesmo operador, mesma máquina, mesmo dia e a mesma quantidade —, separados por segundos. Um com os horários certos (chegada, ajuste, produção, paradas) e o outro vazio: sem chegada, sem ajuste, sem início, sem parada nenhuma. Só o número repetido — e esse número entrava na conta do produzido.
🔍 Por que acontecia: quando o operador larga o pedido (🔄 Passar pro próximo, ou fim de turno), o app grava o registro dele e encerra aquele trabalho. Só que a quantidade é salva com 1,5 segundo de espera — e esse salvamento atrasado recriava do zero um trabalho vazio, só com o número dentro. Na hora de sair, esse fantasma virava um segundo registro. Nem a limpeza automática de cópias enxergava o par: ela compara os horários, e o fantasma não tem nenhum.
✅ Agora: quantidade só entra em trabalho que ainda existe. Pedido largado, passado pro próximo ou reiniciado pelo PCP não volta por causa de um número atrasado — e nunca mais vira registro sozinho.
🛟 De brinde: pedido que o PCP reinicia do zero também deixou de ressuscitar por esse caminho — antes o app podia creditar produção que você tinha acabado de anular.
⚠️ Nada muda pra quem está produzindo: com o pedido na mão, a quantidade continua sendo gravada e aparecendo ao vivo no PCP, igual a hoje.
🧹 Os dois que já estão no sistema continuam lá — FK GRUPO · 31644 (Slotter marcando 943 cx, o certo é 717) e TCHETTO · 30 MOLHO 15X150ML (13.217 cx num pedido de 7.000, o certo é 7.500). Anular as cópias é decisão sua, e não apaga nada: o original continua legível.
🔧 Pro Luan: nada.
🏢 Cadastro da empresa que fatura: digite o CNPJ e a Receita preenche o resto.
🚨 O que estava quebrado: com a razão social escrita na tela, o Salvar respondia "A razão social é obrigatória". Os campos deste formulário tinham o mesmo nome dos campos da tela 🏢 Dados da Empresa (a do cabeçalho dos PDFs) — e o sistema lia os DE LÁ, que estavam vazios. Pior: com aquela tela preenchida, o Salvar teria gravado o CNPJ da JP na outra empresa. Cada campo daqui virou um nome só dele.
🔍 CNPJ no topo, com o botão Buscar — o mesmo do cadastro de cliente. Vem razão social, nome fantasia, CNAE, endereço, município, UF, CEP, código IBGE e telefone. A Inscrição Estadual não vem (ela é da SEFAZ do estado, não da Receita) e a tela diz isso.
⚠️ O regime tributário NÃO se mexe sozinho. A tela escreve o que a Receita respondeu ("é optante pelo Simples desde 01/01/2021") e avisa quando bate ou não com o que está escolhido — mas quem decide CRT 1 ou 3 é o contador: o regime decide a nota inteira (CSOSN × CST).
🛟 Editar deixou de apagar o endereço. A lista de empresas não devolvia endereço, então o formulário abria com esses campos em branco e o Salvar mandava vazio por cima. Agora ela devolve — e, por garantia, campo que a tela não chegou a mostrar não é enviado.
♻️ Desmarcar "Ativa" não some mais com a empresa: ela continua na lista marcada como INATIVA, e é só remarcar pra voltar.
🔧 Pro Luan: `pm2 restart all` (a rota /api/fiscal/emitentes mudou — passou a devolver endereço e aceita ?todos=1). Sem o restart a tela funciona igual, só não mostra o endereço já cadastrado nem as empresas inativas. Migration: nenhuma.
🚨 O "📋 Custo completo" do orçamento estava PRONTO e não aparecia em lugar nenhum — agora tem botão. Você perguntou onde ele estava; a resposta é que ele nunca tinha sido ligado na tela.
📋 Onde fica agora: Orçamento ▸ no quadro verde do 💡 Preço inteligente sugerido, botão 📋 Custo completo. Ele abre a conta linha a linha: papel, cada máquina (com as horas e o R$/h), tinta, insumos, frete e ferramenta — e escreve "não cadastrado" em vermelho no que está faltando, em vez de fingir que é zero.
💰 O "preço pelo custo" veio junto, no mesmo lugar: os dois preços lado a lado (o por kg de hoje e o calculado pelo custo real), com a margem de um no outro.
🔗 E isso destravou duas telas que estavam mudas: o 📊 Pós-cálculo e o ⏱ tempo previsto no app do operador dependiam da memória de cálculo que só nascia quando este painel rodava. Como ele nunca rodava, o pedido saía sem o orçado gravado e as duas telas ficavam sempre em branco — sem dar erro nenhum. Agora enchem sozinhas conforme os orçamentos novos virarem pedido.
🧪 Teste novo pra isso não voltar: ele não pergunta se a função existe (existia!) — pergunta se alguém a chama e se o lugar de desenhar está na tela. Rodado contra a versão que estava no ar, acusa os quatro pontos.
🔧 Pro Luan: nada.
🔓 ACHADA E CONSERTADA a causa do App do Vendedor não deixar ninguém entrar. Quem descobriu a linha certa no servidor foi o Luan.
🧨 O que era: o crachá de acesso vale 30 dias, e o sistema pedia esse prazo ao banco de dados numa unidade que não cabe na versão de PostgreSQL que roda aqui. O banco recusava a gravação e ninguém entrava. Não era senha, não era permissão, não era o celular.
📅 Está assim desde 25/08 — foi a versão que subiu o prazo do crachá de 7 para 30 dias (7 dias cabiam; 30 não). Ninguém percebeu por 6 dias porque quem já estava com o app aberto continua usando o crachá antigo: só quem precisa de um novo bate no muro. Foi o que aconteceu com a Tatiane, depois de ter a senha trocada.
✅ Agora entra normal, e o prazo continua sendo 30 dias — mudou só a forma de pedir a data pro banco. Nada foi afrouxado: quem entra continua precisando do crachá.
🛡️ Os outros 3 lugares que faziam a mesma conta foram junto (inclusive o login do sistema, aqui no PC). Hoje os prazos deles cabem — mas era a mesma armadilha esperando o dia em que alguém aumentasse um prazo.
🧪 E o teste que tinha dado "tudo certo" estava mentindo: ele rodava numa versão de banco mais nova que a do servidor, justamente uma em que o problema não existe. Passou a rodar na versão antiga — foi aí que ele acusou o erro na hora.
🔧 Pro Luan: atualizar o código da API e pm2 restart. Sem migration. Obrigado pela linha do log — foi ela que fechou o caso.
🔑 Quando o App do Vendedor não deixa entrar, a tela passa a DIZER o motivo — em vez de "Erro interno no servidor".
🔁 O que aconteceu (31/08, 15:14): a Tatiane digitou a senha certa e levou "Erro interno no servidor (ref: 5h8e1m)". Redigitou várias vezes achando que o erro era dela. O 🔑 Acesso do administrador deu o mesmo erro — e foi isso que mostrou onde estava: as duas telas não têm nada em comum a não ser o passo de abrir o crachá de acesso, logo DEPOIS de a senha ser aceita.
🧭 Detalhe que engana: senha errada responde "Senha incorreta". Ou seja, receber "erro interno" era a prova de que a senha estava certa — e mesmo assim a frase fazia a pessoa duvidar de si. Pra diagnosticar login travado, digite uma senha errada de propósito: se a mensagem muda, o problema não é a senha.
💬 A frase nova: "Sua senha está certa, mas o servidor não conseguiu abrir seu acesso. Avise o PCP — tentar de novo não resolve." Ninguém fica no teclado tentando à toa — e o freio de 15 tentativas, que é por IP (a fábrica inteira sai por um só), para de ser queimado por engano.
🩹 Uma das causas se conserta sozinha: se o contador interno da tabela de acessos ficar pra trás — o que acontece quando o banco é restaurado de um backup — o sistema realinha e o vendedor entra na mesma hora, sem chamar ninguém. Nada é apagado.
🔎 O log do servidor passou a dizer o código exato do erro e quem tentou entrar. Antes sobrava só a etiqueta curta (aquele ref:), que serve pra achar a linha mas não diz nada sozinha.
🔒 O que NÃO mudou: senha errada continua "Senha incorreta", e ninguém entra sem crachá. Deixar entrar sem ele abriria o app vazio, dizendo que não existe orçamento nenhum — foi exatamente o susto de 25/08, com três propostas dela esperando aceite.
🔧 Pro Luan: atualizar o código da API e pm2 restart. Sem migration. ⚠️ Antes de reiniciar, rodar pm2 logs --lines 5000 --nostream | grep 5h8e1m — essa linha diz a causa exata do caso da Tatiane, e ela se perde no restart.
💬 Agora dá pra RESPONDER o vendedor aqui mesmo — e a conversa fica no pedido.
🔁 O que incomodava: ele manda o pedido com um recado ("Entrega desejada 11/09 — dia 20/09 é mt tempo") e você só tinha duas saídas: aprovar calado ou recusar. Pra explicar que a data é essa mesma, era WhatsApp — e aí a resposta não ficava em lugar nenhum.
✅ Ao aprovar, o sistema já pergunta se você quer responder, com a data que ficou valendo escrita ("Aprovado! A entrega fica 20/09/2026.") e mostrando o que ele escreveu. Dá pra trocar o texto todo, e Esc aprova sem mandar recado nenhum.
💬 Todo pedido dele ganhou 💬 Conversa — esperando, aprovado ou recusado. Você escreve aqui, ele lê no app; ele responde no app, você lê aqui. Quem falou e a que horas fica registrado.
🔔 Recado novo acende o número na aba 📨 Solicitações (e a aba 📦 Pedidos no app dele). Abrir a conversa dá por lido.
✕ Recusar continua igual — e agora o motivo também entra na conversa, pra ele responder ali mesmo em vez de ligar.
🔧 Pro Luan: nada.
⏱ Quem está na máquina passa a ver quanto tempo o pedido tinha pra durar. No app do operador, na tela do pedido: "2h00 de 4h00", com a barra andando, o ajuste e a produção separados e o aviso quando passa — "⚠ 2h00 acima do previsto".
🔒 Só TEMPO. Nenhum dinheiro vai pro tablet. Nem custo, nem preço, nem margem — e não é só uma questão de não mostrar na tela: o que o aparelho baixa passou a ser apenas as horas de cada máquina. O orçamento inteiro (que tem o preço do cliente dentro) continua sem sair do sistema.
🔘 Nasce DESLIGADO e é você que liga: Configurações ▸ ⏱ Mostrar o tempo previsto no app do operador. Enquanto não ligar, o app é exatamente o de hoje.
⏸️ A parada conta junto (a máquina ficou presa ao pedido do mesmo jeito) e aparece separada, dizendo isso. É a mesma conta do 📊 Pós-cálculo do sistema — se fosse diferente, a mesma produção teria dois tempos.
👀 Avisa, não cobra: passar do previsto não trava nada e não manda recado pra ninguém. É informação pra quem está produzindo.
📋 Só aparece em pedido que nasceu de orçamento (da v2.37.610 pra cá) e só na máquina dele — se a máquina não foi orçada, não inventa previsão.
🔧 Pro Luan: nada.
v2.37.625
🧻 A tela do papel de terceiro passa a dizer DE ONDE vem a diferença.
Ela já avisava "livro × rolos com diferença de X kg". Só que avisar não resolve:
pra acertar, você precisa saber quais rolos formam aquele número. Agora tem
o bloco I · Acerto do saldo, que mostra:
• a diferença linha a linha (papel e gramatura), da maior pra menor — é por
onde começar;
• os rolos sem nota: estão no pátio, com peso, mas nunca entraram pelo livro
— com código, lote, data e peso de cada um;
• os tocos sem o rolo-pai, que podem estar contando duas vezes;
• e quanto sobra sem explicação, que é conferência no pátio.
Nada é acertado por aqui, de propósito.
Ajustar papel de terceiro é conversa com o cliente — um botão de "acertar
automático" transformaria isso num clique que ninguém audita depois. O bloco só
aparece quando há diferença: painel que diz "tudo certo" toda semana vira paisagem
e ninguém lê no dia que importa.
📐 Os limites da sua máquina de Corte e Vinco viraram cadastro — acabou o redigitar.
🔁 O que incomodava: a puxada mínima, a puxada máxima do cilindro e a boca ficavam escritas na tela do 🎨 Projetar Corte e Vinco e voltavam ao padrão toda vez que você abria. Quem tem máquina diferente digitava os três de novo, e bastava esquecer um pra o aviso de "não cabe no cilindro" sair pela máquina errada.
⚙️ Agora: cadastre uma vez em Orçamento ▸ Configurações ▸ 📐 Limites da máquina de Corte e Vinco. O desenho real passa a abrir já com os seus números, e o próprio bloco diz de onde eles vieram.
🧪 Os campos continuam editáveis na tela do desenho — dá pra experimentar "e se a boca fosse maior" sem mexer no cadastro. O que vale no dia a dia é o que está cadastrado.
⚠️ Nada muda pra quem não cadastrar: os valores nascem com os de hoje (300 · 950 · 2.200 mm), então o aviso do cilindro continua funcionando igual desde o primeiro minuto.
🔧 Pro Luan: nada.
v2.37.623
🧻 O e-mail semanal do papel passa a levar o link do portal.
O envio automático foi feito antes do portal do cliente. Então o cliente
recebia o relatório da semana e não ficava sabendo que pode consultar o papel dele
quando quiser. Agora o e-mail leva um botão "Ver o meu papel", que abre o
saldo, o extrato e todos os relatórios anteriores.
O link só sai quando existe de verdade: se
o cliente não tem o endereço gerado na ficha, ou se o endereço do site não estiver
configurado no servidor, o e-mail vai sem o botão — nunca com um link que não abre.
E o envio nunca cria o endereço sozinho: quem cria é você, na ficha do
terceiro.
⚡ A máquina parou de rodar o catálogo: o orçamento passou a saber que caixa difícil é mais devagar. Era a última peça do estudo da Salinas que faltava.
🐢 O que ficou de pé: a velocidade cadastrada é a da caixa fácil. A mesma máquina rende MENOS quando tem mais cor pra registrar, quando a chapa é grande demais e quando a onda é dupla (papelão mais duro). Agora o sistema desconta cada uma dessas coisas na hora de calcular as horas — e a hora certa vira preço certo.
⏱️ E o acerto por cor entrou na conta. Trocar tinta e registrar cor a cor leva tempo e não estava em lugar nenhum: agora são X minutos por cor, na impressora.
⚙️ Você cadastra em Orçamento ▸ Configurações ▸ ⚡ Velocidade efetiva: quanto perde por cor, quanto perde com chapa grande (e a partir de quantos mm), quanto perde com onda dupla e o acerto por cor.
👀 O painel Custo completo explica cada perda: "1.000 → 679 cx/h (−32,1%: 3 cores, chapa de 2400 mm, onda dupla)". Número que muda sem explicação é o que faz a gente desconfiar do sistema — aqui está escrito de onde veio.
🎨 Cor só pesa onde se imprime: a coladeira não fica mais lenta porque a caixa tem 4 cores; ela perde só por chapa grande e onda dupla.
⚠️ Nada muda até você cadastrar: com tudo em 0 (como está hoje) o preço é byte a byte o de ontem. É o cadastro que liga. E a máquina nunca cai abaixo de 20% do catálogo, por mais fator que se ponha — se exagerar, a tela avisa em vez de triplicar o preço calada.
🔧 Pro Luan: nada.
v2.37.621
🧾 O simulador fiscal estava inventando imposto na industrialização.
Quando o cliente manda o papel e a JP só transforma em caixa, a nota sai como
industrialização: CFOP 5125/6125, com ICMS e IPI suspensos — a nota
real não cobra nenhum dos dois. A pré-nota já sabia disso desde a v2.37.618, mas
o simulador não: ele calculava tudo como venda.
Na caixa de referência, o simulador mostrava R$ 5.317,62 de imposto por nota
que a nota de verdade não tem. Quem olhasse aquele número pra decidir preço
decidia em cima de um custo que não existe.
Agora o simulador e a pré-nota fazem a mesma conta.
Venda continua exatamente igual — quem não
marcar industrialização vê o mesmo número de sempre. E PIS e COFINS continuam
sendo cobrados na industrialização: zerar tudo "porque é suspensão" seria
errado. O par de CFOP e a suspensão não foram chutados — saíram da conferência
das notas reais da empresa no Sectra.
v2.37.620
🔗 O cliente agora consulta o papel dele sozinho, quando quiser (F5 do plano DCX).
Um link, e pronto. Na ficha do terceiro (Cadastros ▸ 🏭 Terceiros) tem o botão
🔗 Gerar link do cliente. Você copia e manda uma vez; ele guarda. Abrindo, o cliente vê
o saldo do papel dele aqui dentro, quantas bobinas são dele (e quantas estão na
máquina), as últimas movimentações e todos os relatórios semanais que já recebeu —
podendo abrir qualquer um deles e rever os números daquela semana. Funciona no celular.
Ele para de ligar perguntando "quanto do meu papel ainda tem aí?". E quando perguntar
de algum número, os dois estão olhando exatamente o mesmo documento, com o mesmo número.
🚨 O que esse link NÃO mostra. Só o papel daquele cliente: nada de outro cliente,
nada de preço, custo ou margem, nada de nome de funcionário. É só leitura — não existe
um botão ali que mude qualquer coisa no sistema. Link com problema? A chavinha Link ligado
desativa na hora, e o botão gerar outro invalida o antigo (com aviso antes, porque isso
quebra o link que o cliente guardou).
Um detalhe que só apareceu porque foi testado: a proteção contra
alguém ficar chutando links estava barrando também o cliente certo, quando os dois saíam
do mesmo lugar (o wi-fi da empresa dele, por exemplo). Agora quem tem o link certo entra sempre;
o freio só existe pra quem está errando.
🔧 Pro Luan: nada a fazer além do restart de sempre — sem migration; o link mora na ficha do terceiro.
v2.37.619
📨 O relatório do papel do cliente vai sozinho, toda semana (F4 do plano DCX).
Como funciona. Na ficha do terceiro (Cadastros ▸ 🏭 Terceiros) tem um campo novo:
o e-mail que recebe o relatório, com uma chavinha pra ligar ou desligar por cliente.
Toda semana o sistema confere a última semana fechada e manda o relatório dela pro
cliente — com o número oficial, os 6 blocos e os números do fechamento.
🚨 Ele nunca inventa um relatório. O que vai pro cliente é o documento que já foi
emitido aqui dentro. Se a semana fechar e ninguém tiver emitido, quem é avisado é a
JP — o cliente não recebe nada. Documento que sai numerado tem que ser o mesmo que
está guardado.
🚨 E nunca manda duas vezes. A semana já enviada não vai de novo, nem se alguém
clicar em "Mandar agora", nem se o servidor reiniciar no meio. E se o envio falhar,
o sistema não marca como enviado: tenta de novo na próxima — senão a semana sumiria
caladinha, marcada como entregue sem nunca ter saído.
O quadro H, na tela do Papel de Terceiro, responde a pergunta chata: por que o
cliente não recebeu? Ele mostra o estado do envio, se a conta de e-mail está no
servidor, qual semana está sendo cobrada e, cliente por cliente, o motivo — sem e-mail
cadastrado, desligado na ficha, semana sem relatório emitido, já enviado. Tem também o
botão 📨 Mandar agora.
🔧 Pro Luan: o envio nasce desligado de propósito — e-mail pro
cliente não se liga por acidente de deploy. Pra ligar: PAPEL_ENVIO=teste (tudo
cai num e-mail seu, dizendo pra quem iria) e, depois de conferir, PAPEL_ENVIO=ligado.
Precisa também da conta de envio no .env e da migration 044 — sem numeração
oficial o sistema se recusa a mandar, porque relatório com número provisório não serve
pro cliente arquivar.
v2.37.618
📧 Achado sem querer: NENHUM e-mail do sistema estava saindo — e ninguém tinha como saber.
Preparando o envio automático do relatório da DCX, descobri que as configurações do
servidor (as que ficam no arquivo .env) nunca chegavam no enviador de
e-mail. Ele procurava a chave, não encontrava, desistia caladinho e escrevia um
aviso num log que ninguém lê. Não dava erro, não dava aviso na tela: simplesmente
não saía.
O que isso afetava: o "esqueci minha senha" (a pessoa pedia, nunca
recebia) e os avisos por e-mail do Desenvolvimento. Pode estar assim há meses.
Agora as configurações chegam onde precisam. Com uma trava importante: o que
já está configurado no servidor continua mandando — se o arquivo pudesse
atropelar, ele trocaria a porta em que o sistema abre e o app inteiro sairia do ar.
O servidor manda; o arquivo só preenche o que falta.
⚠️ Isto destrava o e-mail, não liga sozinho: pra sair
e-mail de verdade o Luan ainda precisa pôr a conta de envio no .env e
reiniciar. É também o primeiro passo do envio automático do relatório semanal do
papel de terceiro (F4 do plano DCX).
v2.37.617
🔩 Quatro arestas do número oficial (a 616 continua fazendo tudo que dizia — isto aqui é o acabamento).
1) A aba não fica mais em branco esperando. Ao imprimir, o sistema pede o número ao servidor; nesse meio segundo a aba abria vazia e parecia travamento. Agora ela diz "gerando o relatório e pedindo o número ao servidor…" até o documento entrar no lugar.
2) Emitir em bando não trava mais no limite. Quando várias pessoas emitem ao mesmo tempo, quem chega por último precisa tentar de novo até achar o seu número — e o limite de tentativas era exatamente o número de emissores que a fábrica aguentava. Agora tem folga de sobra: ninguém leva "tente de novo" num clique legítimo.
3) Link torto de relatório responde "não existe", não "erro do servidor". Um endereço com id inválido ia direto pro banco e voltava erro técnico — é a mesma pegadinha que já derrubou a pré-nota (o código da caixa numa coluna que só aceita id).
4) Período pedido de trás pra frente é recusado. Perguntar o saldo com a data de início depois da data de fim devolvia tudo zero — que parece resposta e não é. Agora avisa em vez de responder "não houve movimento" pra uma pergunta malfeita.
Nada muda pra quem já estava usando; o Luan continua precisando só da migration 044 + restart (o passo a passo é o mesmo).
v2.37.616
🧻 O relatório do papel de terceiro ganha NÚMERO OFICIAL.
Até agora o relatório semanal do papel do cliente saía com um número
provisório, calculado na hora. Agora ele é emitido e numerado de verdade,
fica guardado, e a tela mostra quais semanas ainda não têm relatório — os
buracos param de passar despercebidos.
Enquanto o servidor não for atualizado, nada
muda e nada quebra: a tela percebe que a numeração ainda não está instalada,
continua saindo com o número provisório da semana e diz isso na tela — em vez de
dar erro vermelho. Quando o Luan rodar a atualização do banco, os números passam
a ser oficiais sozinhos.
📊 O PÓS-CÁLCULO: aquele pedido que você orçou deu quanto de verdade? É a última peça do estudo da Salinas que faltava — o sistema sabia orçar e sabia apontar, e as duas metades nunca se olhavam.
🆕 Aba nova em 💰 Financeiro ▸ 📊 Pós-cálculo. Cada pedido numa linha: faturou × custo orçado × custo real × quanto sobrou, com a margem que saiu ao lado da que foi prometida. Em cima, o placar do período — inclusive quantos pedidos estouraram a hora de máquina.
⚙️ Toque na linha e abre o detalhe máquina por máquina: hora orçada × hora apontada pelo operador, com o ajuste, a produção e as paradas separados (é a parada que explica a diferença, com o motivo). Máquina que rodou fora do orçamento aparece marcada.
📌 A tela diz o que é medido e o que não é. Só a MÁQUINA tem apontamento por pedido; papel, tinta, insumo e frete vêm do orçamento — e isso está escrito em cada pós-cálculo. Chamar de "custo real" um número herdado seria mentir com cara de precisão.
🕐 A hora que custa é a hora OCUPADA (ajuste + produção): a parada fica dentro dela, porque a máquina esteve presa ao pedido do mesmo jeito. É o contrário do OEE — lá a pergunta é quanto rendeu, aqui é quanto custou.
⚠️ Só entra pedido que NASCEU de um orçamento (da v2.37.610 pra cá, quando o sistema passou a guardar a memória de cálculo) e já tem produção apontada. Pedido antigo não aparece: reconstruir o orçamento de trás pra frente seria inventar o passado.
🔒 Vê quem já vê o DRE (admin e financeiro). 🔧 Pro Luan: nada.
💸 O prazo de pagamento entrou no preço — quem paga em 60 dias paga o custo do dinheiro.
📖 A regra (a do estudo da Salinas): taxa ao mês (Orçamento ▸ Configurações ▸ "Juros ao mês") × prazo médio da condição ÷ 30, embutida no preço por dentro. Ex.: 2,5%/mês com 30/45/60 (média 45 dias) = +3,75%. À vista não muda nada.
🧾 Quase tudo já existia: a condição já estava no orçamento (vem sozinha do cadastro do cliente) e o prazo médio já estava no cadastro dela (🧾 Condições de Pagamento) — faltava só a conta entrar no preço.
🔗 Vale nos dois preços — o padrão (por kg) e o "preço pelo custo" leem a mesma condição e a mesma taxa, por um resolvedor só. Antes cada um olhava pra um lado.
📋 O painel Custo completo mostra o juro na conta ("− juros do prazo 3,75% · 45 dias") e avisa quando a condição escolhida está sem o prazo médio preenchido — condição sem dias não é a mesma coisa que à vista.
⚠️ Nada muda até você cadastrar a taxa: com "Juros ao mês" em 0 (como está hoje), o preço é byte a byte o de ontem. É o cadastro que liga.
🔧 Pro Luan: nada.
v2.37.613
🏷️ A etiqueta do tablet volta a sair com a LOGO — e o número de baixo passa a ser o certo.
1) Por que a logo não saía. O sistema manda a logo junto com o pedido pro tablet,
e a etiqueta sabe desenhá-la desde a v2.26.2. Só que o app do operador monta o pedido
campo a campo, e esse campo não estava na lista — chegava vazio nas 4 impressões,
e toda etiqueta do tablet saía com o nome escrito no lugar da marca. No computador
saía certo, porque lá a logo vem do cadastro.
2) E a reimpressão também. O tablet agora guarda a logo de cada cliente.
Isso importa porque o pedido some da lista assim que fecha: na hora de reimprimir pela
tela de Concluídos, o app não achava mais o pedido e a logo sumia de novo. Guarda só o
endereço da imagem, nunca a imagem.
3) O número de baixo era o SALDO, não o pedido. No FK GRUPO 35600 o pedido
era de 2.000 caixas, 318 já tinham ido, e a etiqueta anunciava 1.682 como se fosse o
pedido inteiro. Agora sai a soma do lote que está sendo impresso — a conta certa,
igual à etiqueta do computador.
Sem logo guardada, a etiqueta segue como sempre foi:
o nome do cliente. Nada trava.
v2.37.612
🧩 O micro ganhou aba própria, e a chapa aposentada sai das listas.
Aba nova: Cadastros ▸ 🧩 Chapas de Micro. O material de micro e cartão
agora tem lugar próprio. A aba Chapas continua mostrando tudo junto,
como sempre foi — nada saiu de lá.
Chapa inativa some de onde se ESCOLHE, não de onde se consulta. Uma chapa
marcada como inativa deixa de aparecer no cadastro de caixa, no orçamento, no app
do vendedor e no Desenvolvimento — mas continua no cadastro de Chapas, e continua
na ficha de quem já usa. Nada foi apagado.
O vendedor de caixa vê só chapa. Pedido seu: "quando o vendedor de caixa
está vendendo a caixa, ele só pode ter acesso à chapa — o micro tem várias
extensões e vai ficar uma lista muito grande, muito difícil pro vendedor
entender". O app do vendedor vende CAIXA, então micro e inativa saem da lista.
Duas travas de segurança que valem saber: a
chapa que um cadastro JÁ usa continua na lista, marcada com ⚠️ — se a opção
sumisse, o navegador cairia na primeira da lista e trocaria o material do seu
cadastro em silêncio. E se o arquivo novo não carregar, a lista sai inteira, como
era antes — nunca vazia.
v2.37.611
🧻 Papel de terceiro não roda pra outro cliente sem avisar — e a Perda de Papel ganhou o recorte por dono.
1) O aviso do papel trocado (F2 do plano DCX). Na onduladeira, ao ler o rolo, e no 📐 Programar do PCP, na sugestão de rolos: se um rolo de TERCEIRO (ex.: DCX) casar com pedido de outro cliente, acende o amarelo na hora — "rolo do dono X num pedido de Y". Avisa, não trava (§9.5: heurística não decide; quem decide é gente). Se for de propósito, o caminho certo é a troca de dono no Estoque de Bobinas — nunca rodar calado. A régua é UMA só (js/75) pros dois lugares.
2) 📄 Perda de Papel filtrada por dono. Seletor novo "🧻 todos os donos": escolhendo a DCX, entram só os rolos DELA fechados no período e os pedidos amarrados por leitura de rolo — a pergunta "quanto do papel DELA virou perda?" agora tem número próprio. No "todos os donos", tudo como sempre foi.
Detalhe honesto: o recorte só enxerga produção que LEU o rolo — o que rodou sem leitura fica fora do recorte (e continua aparecendo no total geral). E o "toco" que nasce na balança (a sobra que vira rolo filho) não conta como consumo — era o elo fantasma da v606, e a mesma trava vale aqui.
v2.37.610
💰 O orçamento passou a saber quanto a caixa CUSTA — e continua mostrando o preço por kg de hoje.
1) O programa de entregas cobrava insumo de menos. Pela MESMA caixa e a MESMA
quantidade, o painel cobrava R$ 0,44/cx de insumo e o programa de entregas cobrava
R$ 0,00 — a conta era feita antes de saber a quantidade. Pallet, fitilho e stretch
saíam de graça em toda entrega parcelada. Consertado, e agora existe uma porteira: quem
esquecer a quantidade recebe aviso em vez de um número errado calado.
2) Custo completo do item (só leitura): papel, máquinas (acerto + rodagem pelo
custo-hora), tinta e acabamento, insumos linha a linha, frete e ferramental — com
"não cadastrado" em vermelho onde a parcela é 0 por falta de cadastro.
3) Memória de cálculo: o item guarda de onde saiu cada número, com a versão e a
data. Reabrir compara com o recálculo de hoje e avisa se divergir mais de 0,5% —
sem mudar o recálculo. O pedido gerado leva essa memória junto.
4) Preço pelo custo (o principal): custo líquido ÷ (1 − impostos − margem), com
quebra em cascata de trás pra frente, créditos só no regime real, juros pelo prazo do
cliente e frete por km. O item mostra os dois preços lado a lado — o de hoje e o
pelo custo — com a margem implícita de um no outro. Na caixa de referência:
vende a R$ 16,11 e custa R$ 8,62 — margem real de 17%.
Nada muda no seu preço agora. O modo nasce em
"R$/kg (o de hoje)" e todo campo novo nasce em 0. Enquanto você não cadastrar, o preço de
todo orçamento sai igual ao de hoje — a tela só passa a dizer o que está faltando. Onde
cadastrar: 💰 Centro de Custo (R$/km, kg por viagem), ⚙️ Máquinas ▸ Custo-hora (quebra,
acerto, base) e Orçamento ▸ Configurações (regime, juros, prazo, margem sobre o preço).
v2.37.609
📐 O orçamento passou a orçar pela chapa de VERDADE.
No 🎨 Projetar Corte e Vinco do orçamento agora tem o 📐 Desenho real da faca.
Quando você usa ele, o Aplicar ao orçamento leva a chapa que o desenho mediu —
não mais a conta por fórmula.
E o principal: o orçamento parou de fechar caixa que a máquina não faz.
Uma bandeja 300×250×150 dá 968 mm de puxada e o cilindro só puxa 950.
Até ontem isso passava calado e só aparecia na fábrica. Agora o sistema
pergunta antes de aplicar, dizendo o quanto passou e qual é o limite —
e você decide: voltar e girar o desenho, mudar as poses, ou seguir assim mesmo.
Também avisa quando as poses ficam com a onda cruzada (na chapa a onda tem
um sentido só).
Se você não abrir o desenho real, nada muda: o orçamento
segue pela fórmula, exatamente como sempre foi. Fechou o modal, a chapa do item anterior
não vaza pro próximo.
v2.37.608
📐 O desenho REAL da faca entrou no Corte e Vinco.
Em Cadastros ▸ Caixas ▸ Corte e Vinco nasceu o botão 📐 Desenho real da faca.
Ele desenha o molde de verdade — não um retângulo de conta — e já vem com o que a
máquina precisa saber:
• Sentido da onda e posição na máquina (deitado, em pé ou encaixando sozinho nos limites);
• Aviso do limite da máquina: fala na hora quando a puxada passa do cilindro ou fica abaixo do mínimo;
• Arranjo das poses na mão: arrasta pra mover, duplo clique pra girar 90° — a chapa e o aproveitamento recalculam ao vivo;
• Baixar a faca em DXF, SVG ou imagem.
Três modelos desenhados a partir de DXFs reais do ArtiosCAD: Bandeja F0427,
Divisórias FEFCO 0933 e Cartucho Fundo Automático. As medidas e a onda já vêm
preenchidas do que está no cadastro da caixa — é só abrir.
Nada do que já existia mudou: a biblioteca de modelos, o molde por
fórmula, o arranjo de poses e o importar DXF continuam iguais, no mesmo lugar. O desenho real fica
logo abaixo e só carrega quando você clica.
✂️ Projetar Corte e Vinco pelo orçamento: trocar o modelo não mudava o molde. Você escolhia "Cartucho ECMA" e a tela continuava mostrando a fórmula e o desenho da maleta — o seletor dizia uma coisa e o desenho outra, sem um aviso sequer.
🔍 Por quê: o cadastro de caixa liga esses campos por conta própria; a tela aberta pelo orçamento nunca passava por ali. Então modelo, onda, caliper e aba de cola não recalculavam nada.
📏 A onda agora vem da chapa que você escolheu no item — e é dela que sai o caliper (onda B = 3 mm, BB = 5,8 mm, E = 1,5 mm, do cadastro de ondas). Antes o painel abria sempre em "B": uma chapa BB era desenhada com 3 mm de espessura, calada.
⚠️ E o "0 × 0 mm" acabou. Com o gerador em Biblioteca ArtiosCAD e nenhum modelo escolhido, a tela mostrava molde 0 × 0, caliper 0, desenho em branco e área zero — sem dizer o que faltava. Agora ela diz: "escolha um modelo na biblioteca acima".
O cadastro de caixa não mudou em nada: o conserto só liga o que já estava solto na tela do orçamento.
🧻 Papel de Terceiro — o extrato do papel do cliente, com relatório semanal. Tela nova em Análises: escolhe o DONO do papel (ex.: DCX) e a SEMANA, e sai o retrato inteiro — saldo papel a papel (anterior + entradas − consumido na balança = final), o consumo POR PRODUÇÃO com a onda, os rolos e o lote da bobina, a perda por onda, as cargas da semana que levaram produto do dono (quantidade e peso), as entradas por NF e a posição dos rolos, com alerta de rolo parado há mais de 60 dias.
🖨️ Imprimir relatório monta o documento A4 de 6 blocos pro cliente dar baixa no estoque dele, numerado pela semana (ex.: Nº 2026‑S35). A conta fecha na cara: balança × apontado e livro × rolos aparecem lado a lado — diferença nunca é escondida.
⚓ Nada é amarrado por nome parecido: um pedido é "do dono" porque um rolo DELE foi lido na máquina pra esse pedido; uma carga entra porque leva palete desses pedidos. E a perda por onda compara o fator do cadastro com a faixa de referência da ABPO (onda B: 1,30–1,32) — fator fora da faixa ganha aviso, porque 35% na onda B infla o teórico e esconde perda.
⏱💰 As horas extras saem do relógio de ponto direto pro custo do mês — ninguém digita mais.
📥 Puxou o relógio no RH ▸ Ponto, a conta aparece na hora: o quadro novo 💰 Horas extras do mês mostra funcionário por funcionário — os dias com extra, o total de horas e o custo de cada um (custo mensal ÷ 220 + o adicional). PJ entra sem encargo; benefício fica de fora (o vale não cresce quando a pessoa fica uma hora a mais).
🔗 O total entra sozinho no custo variável do mês — no Painel de Custos, no Ponto de Equilíbrio e nos dois DRE aparece a linha "⏱ Horas extras (ponto)", igual já acontece com o papel e a comissão. Quando fechar o mês, o "sobrou ou faltou dinheiro" já vem com as extras dentro.
⚠️ Não precisa mais digitar hora extra nos Lançamentos. Se o mês tiver as duas coisas — a automática do relógio E a digitada à mão — o Painel avisa em amarelo pra não contar em dobro. O lançamento à mão continua existindo pra extra que o relógio não vê (diarista, empreita).
⚙️ As regras são suas: em Custos ▸ Ponto de Equilíbrio ▸ Ajustes do cálculo dá pra mudar a jornada por dia (padrão 8,8 h = 8h48), a tolerância (15 min), o adicional (50%) e o par máximo de batidas (10 h). Campo vazio = padrão.
🧮 Uma conta só pra todas as telas: a régua nova (js/74) é chamada pelo espelho do ponto, pelo Custos e pelos dois DRE — os números batem em todo lugar. Dia com batida sem par não vira extra (na dúvida, não se inventa custo) e funcionário com extra mas sem salário cadastrado aparece avisado, fora da soma — nada de número chutado.
🔧 Pro Luan: nada a fazer — é tudo tela; o doc ponto_batidas já existia.
⚖️ O Ponto de Equilíbrio passou a contar pelos dados REAIS. O pedido agora conta no dia em que foi entregue de verdade (registro do motorista), não no dia da baixa do faturamento. Era por isso que agosto mostrava 227,8 t: a baixa em lote de 10/08 (150 pedidos, 141 t) puxou pra dentro de agosto 94,8 t entregues em junho/julho — e junho/julho ficaram pela metade. Com a régua nova: junho 42,1 t · julho 95,7 t · agosto 121,5 t.
🗓 Dá pra ver por Mês, Semana ou Dia. Botões novos no topo da tela: escolha um dia e veja quanto entregou contra o fixo do dia (mês ÷ dias úteis do ajuste ⚙️); a semana vai de segunda a domingo contra o fixo de uma semana (mês ÷ 4,3). A margem por kg aplicada é a do mês do dia escolhido.
🧪 Pedido de teste saiu da conta. CLIENTE TESTE somava 0,7 t e R$ 5,7 mil no financeiro como se fosse venda.
Pedido sem registro de entrega real continua contando: vale a data prevista e, em último caso, a da baixa — nada some da conta. O "Resultado por cliente" segue a mesma régua nova.
📐 Agora dá pra ajustar as dobras — clicando na própria caixa. Ontem toda dobra virava 90° e algumas abas levantavam quando deviam ficar deitadas. O DXF não guarda ângulo nenhum: quem sabe é quem monta a caixa. Então clique na aba errada, escolha não dobra · 45° · 90° · 135° · 180°, e ela conserta na hora, na sua frente.
💾 Fica gravado por caixa. Ajustou e salvou, ela monta assim daqui pra frente — pra você, pro vendedor e pro cliente.
🎯 A base também sai daí: no mesmo cartão tem "usar como base" pra escolher o painel que fica parado enquanto o resto levanta.
Detalhe que importa: "não dobra" é ângulo zero, não é apagar a linha. Se apagasse, os dois pedaços virariam um painel só e todas as outras marcas mudariam de lugar — o seu ajuste deixaria de valer na próxima vez que abrisse.
🧊 A caixa em 3D, montada da própria faca. No Desenvolvimento, toda caixa que tem o DXF anexado ganha o botão 🧊 Ver em 3D: o sistema lê a faca na hora, descobre os painéis, monta a caixa e ela gira com o dedo ou o mouse. A barra embaixo monta e desmonta na velocidade que você quiser.
🎯 Você escolhe a base — o painel que fica parado enquanto o resto levanta. Pela lista ou clicando direto no painel.
📐 A onda só aparece onde a faca cortou. No vinco o papel dobra e a capa envolve a quina; antes a onda saía no contorno inteiro e a caixa ficava com cara de serrote nas dobras.
🧪 Conferido contra a prova de 19/08: na CX MITTO 06 o sistema acha os mesmos 15 painéis, com a árvore de dobradiças inteira — mesmo pai, mesma profundidade, mesmo eixo, mesma linha, mesmo lado.
⚠️ O que ainda falta: os ângulos. Toda dobra vira 90°, porque o DXF não diz quantos graus — algumas abas levantam quando deviam ficar deitadas. É a próxima etapa.
Sem faca anexada, o botão nem aparece: nada do que já funciona muda. O desenho 3D (590 KB) só é baixado no primeiro clique — quem não abre o 3D não paga por ele.
💰 Agora dá pra corrigir o VALOR também — e o sistema pergunta POR QUÊ.
✅ O que se edita: valor, data, categoria, descrição, fornecedor, cliente e máquina.
📝 O motivo é obrigatório. Antes de salvar, o sistema pede por que você está mudando — e essa frase fica gravada junto de cada mudança. É o que faz o histórico servir pra alguma coisa daqui a seis meses: sem ela, sobra uma lista de números trocados que ninguém explica.
🔒 Sem motivo, nada acontece. Nem a mudança, nem meia linha de histórico — o lançamento fica exatamente como estava.
💰 Os três que mexem no custo do mês (valor, data e categoria) vêm marcados com 💰 na tela e no histórico, pra dar pra separar de um conserto de texto. Mudar a data pra outro mês move o lançamento de mês, e isso também entra no registro — não é efeito escondido.
🔄 Quem só abriu e não mexeu fecha normal: o sistema não cobra explicação de quem não mudou nada.
📦 Quantidade e produto continuam fora quando o lançamento somou no almoxarifado — mudar sem devolver a quantidade deixaria o saldo mentindo. Pra isso, apagar e lançar de novo (o apagar já devolve).
🔧 Pro Luan: nada a fazer.
✏️ Dá pra corrigir a descrição de um lançamento — e fica registrado quem mudou o quê.
🔍 Como era: lançamento com a descrição errada só tinha um caminho: apagar e lançar de novo. Sumia o registro de que ele existiu, sumia quem lançou, e o mês ficava com um buraco que ninguém explicava depois.
✅ Agora tem o ✏️ ao lado da lixeira. Dá pra corrigir a descrição, o fornecedor, o cliente e a máquina.
📜 Toda mudança vira uma linha com quem fez, quando, de quê e pra quê — visível dentro do próprio lançamento. Na lista, quem foi editado ganha o selo ✏️ editado N×; passando o mouse nele, aparece o histórico.
🔒 O histórico SÓ CRESCE. Editar de novo acrescenta, nunca substitui — nem a segunda edição apaga a primeira. É a regra da casa: nada se apaga.
💰 O que NÃO se edita, e por quê: valor (é dinheiro que já foi pago), data (decide de qual mês é o gasto) e categoria (clichê e faca ficam FORA do custo — trocar faria o lançamento sumir do mês sem ninguém ver). Pra esses, o caminho continua sendo apagar e lançar de novo.
📦 Quantidade e produto também não, quando o lançamento somou no almoxarifado: mudar sem devolver a quantidade deixaria o saldo mentindo. O apagar já sabe devolver — a edição não precisa virar uma segunda porta pro estoque.
🔧 Pro Luan: nada a fazer.
📦 A caixa coletiva entrou no sistema — e o orçamento diz sozinho quantas caixas cabem dentro.
🔍 O que faltava: a coletiva é comprada, tem medida e tem preço — e não existia em lugar nenhum. Um pedido de 15.862 caixas que gasta 84 coletivas a R$ 4,80 tem R$ 403,20 que ninguém somava. Some no unitário, e o cliente paga a menos.
✅ Tela nova: Cadastros ▸ 📦 Caixas Coletivas. Cadastre nome, medida interna (o espaço de dentro), preço e tara.
🧮 Quantas cabem é CALCULADO, não digitado. No orçamento, escolha a coletiva (ou deixe o sistema escolher a mais barata) e ele responde: quantas caixas por coletiva, quantas coletivas o pedido usa, e quanto isso dá por caixa. Conta as deitadas (empilhadas pela altura) mais as em pé no vão que sobra ao lado, e testa a peça nas duas orientações.
💰 A mais barata é por CAIXA, não por coletiva. Uma coletiva grande que leva o dobro pode compensar mesmo custando mais. E coletiva sem preço não ganha por ser “de graça” — ela só entra quando nenhuma outra couber.
⚠️ Quando não dá pra responder, a tela DIZ o motivo — “a peça não cabe nesta coletiva”, “falta a medida da caixa dobrada” — em vez de o preço sair errado calado.
📌 Nada muda até você cadastrar e escolher a coletiva no item. Sem isso o orçamento sai igual ao de hoje.
🔧 Pro Luan: nada a fazer — no MTX isto é uma tabela nova; aqui foi feito sem mexer no banco.
📦 Grampo, cola, fita, stretch, pallet e etiqueta entram no preço sozinhos.
🔍 O que faltava: papel, setup e tinta já saíam do cadastro. O resto não existia em conta nenhuma — o sistema sabia que a caixa é grampeada e usava isso só pra escolher a máquina. E o pallet era o mais gritante: a quantidade já era calculada e impressa na nota do cliente, e nenhum centavo dela entrava no custo.
✅ Onde cadastrar: 📒 Financeiro ▸ 🖨️ Lançamentos ▸ ✏️ Gerenciar insumos — o botão ⚙ de cada um abre “como ele entra no preço”: de que ele depende (caixa, pallet, amarrado, chapa…), quanto gasta e quanto custa.
🧮 Duas contas são especiais, porque não são um número fixo: a FITA fecha no comprimento da caixa dobrada e sobe pela altura do pacote — caixa comprida gasta mais; e o GRAMPO vai um a cada tantos milímetros de aba — caixa de 200 e de 600 mm não levam o mesmo tanto.
🔒 Só cobra o que a caixa usa: caixa colada não paga grampo, caixa sem filme não paga stretch. E caixa sem fechamento cadastrado não paga nenhum dos dois — em branco é “não sei”, não “não”.
📊 O que a fábrica compra inteiro vai inteiro: 77 pallets e meio viram 78. Meio metro de fita existe; meio pallet não.
⚠️ Nada muda até você cadastrar. Sem consumo e preço, o insumo não entra e o orçamento sai igual ao de hoje. E insumo sem preço nunca é chutado — fica de fora e avisa.
🔧 E um conserto que veio junto, que estava no ar: o custo de tinta chegava em uma das cinco contas de preço. O simulador de quantidades e o 📋 Gerar itens calculavam — e gravavam — o item sem a tinta: mais barato que o painel, na mesma caixa. Agora as cinco passam pelo mesmo caminho. O preço do simulador sobe, e é esse o conserto: o painel sempre esteve certo.
🔧 Pro Luan: nada a fazer.
📦 O Estoque PA parou de ir como lista inteira — a raiz do sumiço das caixas.
🔍 Como era: o estoque inteiro subia num pacote só e quem gravava por último ganhava. Em 26/08 um computador com versão antiga recebeu 6 linhas novas, apagou com o código velho e regravou — sumindo pra todo mundo.
🔧 Os consertos anteriores tratavam o sintoma: a v2.37.561 fazia a linha voltar em segundos e a v2.37.562 pôs uma guarda antes de gravar. Agora cada caixa vai uma a uma, e dois computadores mexendo em caixas diferentes não se apagam mais.
🪦 E o que sai de propósito, sai com nome e motivo. Como nada mais some por omissão, a remoção virou registro: fica escrito quem tirou, quando e por quê.
🛡️ Servidor fora do ar na hora de salvar? Grava só o que este computador tem e não apaga nada — não dá pra explicar o que não deu pra ler.
🔄 Ninguém fica pra trás: enquanto a fábrica não atualizar toda, o sistema grava pelos dois caminhos — o novo e o antigo — então um aparelho que ainda não pegou a versão continua enxergando o estoque normalmente.
🔢 Este trabalho estava pronto desde 27/08 e parado, com o número 2.37.575 — que outra sessão tinha tomado no mesmo dia. Renumerado pra 596 e mesclado com os consertos que entraram no meio (a limpeza de cópias da 581 e a marca do ✕ da 585 continuam valendo).
🔧 Pro Luan: falta uma linha — pôr o documento do estoque na lista dos que só aceitam gravação registro a registro (`SO_MERGE` += 'estoque') e reiniciar. Sem isso o conserto já vale entre os aparelhos atualizados, mas um computador com versão velha ainda consegue gravar por cima.
🔒 Nome de cliente com código dentro não roda mais na tela de ninguém.
🔍 O buraco (auditoria de 30/08): as LISTAS do App da Qualidade já tratavam o texto, mas as telas de detalhe jogavam o nome do cliente, o código da caixa e o nº do pedido crus na página. Quem conseguisse gravar HTML no nome de um cliente fazia o código rodar no computador do laudista quando ele abrisse o pedido — e levava o acesso dele junto.
✅ Consertado em 11 lugares: 10 no App da Qualidade e 1 no PCP (o motivo da perda, que era a única coluna crua de uma linha em que todo o resto já era tratado).
🔍 A auditoria apontou 4 — a varredura achou 11. O mais sério não estava na lista: as observações dentro da caixa de texto do laudo, onde bastava escrever a marcação de fechamento pra escapar da caixa.
⚠️ O que NÃO foi mexido, de propósito: a mensagem de WhatsApp e o e-mail do laudo. Ali o nome é texto, não página — tratar faria o cliente ler “M&A Embalagens” no lugar de “M&A Embalagens”.
👍 Nada muda na tela pra quem usa: nome com “&” ou “<” continua aparecendo igual, só que como texto.
🔧 Pro Luan: nada a fazer — mas os itens 1 a 4 do relatório de segurança (trocar o token, fechar a .git, proteger as rotas que apagam em massa e trancar o upload) continuam pendentes e são mais graves que este.
⏱ O tempo de manutenção estava quase todo de fora — faltava a maior das duas fontes.
🔍 Como apareceu: o dono olhou a aba 🔧 Manutenção em 24 meses e viu 0,8 h de parada na Slotter. Desconfiou, e estava certo.
💡 A causa: eu só somava as paradas apontadas DENTRO de um registro de produção. Só que manutenção é justamente quando não há pedido rodando — a máquina quebrou, a produção parou, e o operador aponta a parada avulsa, que fica em outro lugar.
✅ Agora as duas somam. As duas não se sobrepõem: a avulsa é, por definição, tempo parado sem pedido.
⚠️ E o “—” passou a querer dizer ZERO, nunca “não consegui ler”. Se a busca das ordens ou das paradas falhar, a tela diz. E se a consulta bater no teto de 2.000 paradas, ela avisa que o total está por baixo — número cortado com cara de completo é pior que número nenhum.
🔄 Trocar o período agora rebusca as paradas daquela janela — antes reusaria a lista da janela velha e mostraria menos num período maior.
🔧 Pro Luan: nada a fazer.
🔧 Manutenção agora tem dono: cada gasto vai pra MÁQUINA.
🔍 O que faltava: o dado estava partido em dois. O lançamento sabia quanto custou e não sabia de qual máquina; a ordem de serviço sabia a máquina e não tinha valor. Ninguém conseguia responder “quanto gastei de manutenção na Coladeira”.
✅ Ao lançar 🔧 Manutenção ou ⚡ Energia (máquina), aparece o campo Máquina. E ao pedir uma peça em 🛒 Pedidos de Compra também — aí a compra volta do comprador já com dono, sem ninguém ter que lembrar depois.
📊 Aba nova ⚙️ Máquinas / Processos ▸ 🔧 Manutenção: por máquina, o gasto no período, a média por mês, quantas ordens de serviço, o tempo médio de cada uma e as horas paradas por manutenção. Dá pra ver 3, 6, 12 ou 24 meses.
💰 E o ciclo fecha no custo-hora: a manutenção por mês, que era digitada no escuro, agora tem um botão 📈 usar R$ X com a média do que a máquina realmente consumiu.
⚠️ Nada é inventado. Lançamento sem máquina aparece como “não é de uma máquina” e nunca é dividido entre elas — gasto posto numa máquina que não o teve vira custo-hora errado, e custo-hora errado vira preço errado. O campo também é opcional: manutenção do prédio não é de máquina nenhuma.
⌚ Duas medidas de tempo, de propósito: a ordem de serviço conta o tempo do conserto; a parada conta o tempo que a máquina ficou sem produzir. Não são o mesmo número, e as duas perguntas interessam.
🔧 Pro Luan: nada a fazer — não mexeu no banco nem na API.
👷 O custo-hora avisa quando um salário está sendo contado DUAS vezes.
🔍 Como isso acontece: a mão de obra entra dentro do custo-hora, e por isso a folha da produção é descontada da base do rateio dos fixos — senão a mesma pessoa seria paga duas vezes. Só que esse desconto olha o cadastro de funcionários. Se alguém trabalha na máquina e não está cadastrado, a conta não fecha.
📌 Caso real (30/08): a Coladeira estava com “JOAO PEDRO ×3” usando um cadastro só. A máquina cobrava 3 salários (R$ 16.398) e o rateio descontava 1 (R$ 5.466) — R$ 10.932 contados duas vezes, calado.
✅ Agora a tela diz quanto as máquinas cobram de salário, quanto o cadastro tem em produção, e a diferença — nos dois sentidos (sobrando ou faltando gente ligada a máquina).
💡 O certo é cadastrar cada pessoa. Em 2 turnos elas são pessoas diferentes, cada uma com o salário dela — o “×3” só serve pra gente igual dentro do MESMO turno e que já esteja cadastrada.
⚠️ Avisa, não barra, e não mexe em número nenhum: só compara o que está cobrado com o que está cadastrado.
🔧 Pro Luan: nada a fazer.
🧭 O custo-hora agora diz ONDE fica cada cadastro que falta.
🔍 O que estava errado: quando faltava o R$/kWh, o aviso mandava “cadastrar nos ajustes do Centro de Custo” — um nome que não existe no menu. Quem lêsse ia procurar e não ia achar.
✅ Agora ele escreve o caminho: 📒 Financeiro ▸ 📈 Ponto de Equilíbrio ▸ ⚙️ Ajustes do cálculo. E o custo da pessoa aponta pra 📒 Financeiro ▸ 👥 Custos Fixos ▸ Funcionários.
⏰ E o campo das horas ficou claro: ele é das horas da MÁQUINA, não das da pessoa — confundir os dois muda o preço. Agora o campo diz isso, e mostra quanto daria pelo turno cadastrado no Cronograma (ex.: “hoje daria 194 h”), pra conferir de bater o olho.
💡 Deixando o campo vazio, o sistema calcula as horas sozinho pelo turno daquela máquina — que costuma ser o número certo.
🔧 Pro Luan: nada a fazer.
💰 O custo-hora da máquina deixa de ser um número digitado.
🔍 Como era: em Orçamento ▸ Configurações havia um campo por máquina — 850 na Slotter, 520 na Coladeira. Eram números escritos à mão, que não saíam de conta nenhuma: ninguém sabia dizer de onde vinham, nem o quanto mexer quando a energia subia.
✅ Agora existe a tela ⚙️ Máquinas / Processos ▸ 💰 Custo-hora, com as cinco parcelas: depreciação (pelo valor de reposição), manutenção do mês, energia (kW × horas × R$/kWh), mão de obra (quem fica na máquina, com o custo que já está no Centro de Custo) e o rateio dos custos fixos. Divide pelas horas produtivas do mês e sai o R$/h.
📊 A tela mostra a conta inteira — cada parcela por mês e por hora, e de onde saiu cada número. As horas vêm do turno daquela máquina (o mesmo do Cronograma, com o almoço já descontado), ou você digita.
🔒 Nada muda no preço até você cadastrar. Enquanto uma máquina não tiver custo-hora, o orçamento continua usando o número digitado de sempre — exatamente como hoje. Quando tiver, o campo antigo vira espelho e a tela diz qual dos dois está valendo.
⚠️ O sistema nunca chuta. Parcela em branco aparece como não cadastrada e fica fora da conta, com aviso. Um custo-hora inventado viraria preço errado na mão do cliente.
✍️ Tem pressão e ainda não levantou os números? Dá pra digitar o custo-hora à mão na própria máquina — ele manda em tudo, e as parcelas continuam à vista pra completar depois.
📌 Onde cadastrar o resto: o R$/kWh, os dias úteis do mês e as horas/mês da pessoa ficam em 💰 Centro de Custo ▸ Ponto de equilíbrio ▸ Ajustes do cálculo.
📎 Caixa grampeada: o preço cobrava a coladeira mesmo em caixa que nunca passou por ela. Assim que a grampeadeira ganhar custo-hora, ela toma o lugar — e só aí.
🔧 Pro Luan: nada a fazer — não mexeu no banco nem na API.
📅 O pedido agora avisa quando o cliente só recebe com agendamento.
🔍 O que faltava: o cadastro do cliente já sabia que ele exige agendamento — mas isso ficava lá, no cadastro. Quem montava a carga só descobria com o caminhão no portão.
✅ Agora, na Carteira e no PCP, o pedido mostra 📅 precisa agendar junto do status — com as horas de antecedência e com quem marcar, quando isso estiver cadastrado.
⏰ O aviso aparece na hora certa: só quando a mercadoria fica pronta, que é quando dá pra marcar. Não aparece em pedido ainda em produção (seria barulho o ano inteiro) e some depois que carregou.
🔒 E a senha do portal ganhou controle de acesso. Na tela 🔐 Acessos existe agora “Ver senha do portal do cliente”. De fábrica vem ligado para Administrador e PCP.
👉 A Expedição não vê a senha — quem carrega o caminhão não precisa dela (decidido em 27/08). Se um dia precisar liberar alguém, é em 🔐 Acessos, por perfil ou por pessoa.
👁️ Quem não tem essa permissão abre o cadastro do cliente normalmente, mas o quadro do portal fica escondido — e a senha nem chega no computador dela. Se ela salvar o cadastro, o acesso guardado não é apagado.
🔧 Pro Luan: nada a fazer — não mexeu no banco nem na API.
🔐 Agendamento pelo portal do cliente: agora tem onde guardar o acesso.
🔍 O que faltava: quando o cliente só recebe com agendamento pelo portal dele, alguém da fábrica precisa entrar no site do cliente pra marcar a entrega — e o endereço, o usuário e a senha viviam num papel na mesa ou na cabeça de quem sabia.
✅ Agora, no cadastro do cliente, quando você escolhe “Agendar por: Portal do cliente”, abre um quadro pra guardar o endereço do portal, o usuário e a senha.
🔒 Isso fica SÓ no cadastro do cliente. Não sai no romaneio que vai com o motorista, não aparece na ficha do operador, não vai pra tela da doca e não é enviado pros celulares e tablets da fábrica. Só quem abre o cadastro de clientes vê.
👁️ A senha nasce escondida (aparece como bolinhas) e tem um botão Mostrar pra conferir na hora de digitar. Fechar e abrir o cadastro esconde ela de novo.
📌 Quem não agenda por portal não vê nada disso — o quadro só aparece quando o portal é escolhido, pra não poluir o cadastro de quem marca por telefone ou WhatsApp.
⚠️ Um aviso honesto: a senha fica guardada em texto, do mesmo jeito que os outros dados do cadastro. Quem tem acesso à tela de Clientes consegue ver. Isso não é um cofre — é o mesmo lugar onde já ficam telefone e contato do cliente.
🔧 Pro Luan: nada a fazer — não mexeu no banco nem na API.
📋 As ocorrências podiam apagar umas às outras — e 5 já estavam sumidas da tela. Sistema, app do operador e app da Expedição gravavam a lista inteira de ocorrências. Quem salvasse com uma cópia velha levava junto o que os outros tinham registrado — e nem precisava clicar em nada: um PC com cópia velha regravava a lista dele sozinho ao abrir.
🔎 5 ocorrências do operador estavam invisíveis pro PCP (mancha 767 cx no FK, trinca 67, abaulada 10 na Nacon, descolamento 30 na Deusa e mais uma) — 874 caixas de perda que ninguém contava. Todas recuperadas: 112 ocorrências, nenhuma perdida.
✅ Agora cada ocorrência sobe sozinha, uma por uma — não existe mais lista pra atropelar.
⚠️ Muda um número que você lê: os relatórios de perda de junho a agosto sobem 874 caixas. Não é erro novo — é dado que sempre existiu e não era contado.
🏷️ A etiqueta do palete imprimia a medida da caixa de OUTRO cliente. Ela procurava só pelo código e, não achando no cliente do pedido, pegava qualquer caixa com aquele código. Agora começa pelo vínculo forte (a caixa amarrada ao pedido), depois o código do mesmo cliente. Quando a medida vier de outro cadastro, a etiqueta sai marcada ⚠ NÃO CONFERIDA.
🧾 A página onde o cliente aprova imprimia "IPI R$ 15,00" — era a taxa (15%) formatada como dinheiro, na cara do cliente. Se o valor não chegar, a tela não inventa número.
Estes três consertos estavam prontos e testados desde 25/08, parados sem subir. Trazidos pra base de hoje e testados de novo aqui.
📦 "Não consegui ler as caixas" — era o navegador cheio, não a API.
🔍 O que estava acontecendo: você abriu Cadastros ▸ Caixas e apareceu o aviso vermelho "Não consegui ler as caixas da API (The quota has been exceeded.) — salvar bloqueado até recarregar", com a tela marcando 01 caixa no sistema. Dali em diante não dava pra salvar caixa nenhuma até recarregar a página — e recarregar caía no mesmo buraco.
🧩 Por quê: a API tinha respondido certo, com todas as caixas. "The quota has been exceeded." é o recado do navegador avisando que acabou o espaço dele pra guardar a cópia local (é o Safari do seu Mac). Só que o sistema gravava essa cópia bem no meio do caminho: uma linha antes de desenhar a tela e de liberar o salvar. Como a gravação estourava, ele entendia que a leitura tinha falhado — quando as caixas já estavam ali, prontas, na memória.
⚠️ E tinha uma parte pior, que ninguém via: na hora de salvar uma caixa, essa mesma cópia local era gravada antes de mandar pro servidor. Se ela estourasse, a sua alteração não chegava no servidor — sem aviso nenhum na tela.
👥 O cadastro de CLIENTES tinha exatamente o mesmo defeito (com o aviso "Não consegui ler os clientes da API") — e ali ainda havia uma terceira perda, também calada: junto ia embora o envio do perfil de recebimento do cliente pros aplicativos. Ou seja, o tablet do operador e a tela da doca paravam de receber janela de entrega, doca e regra de palete daquele cliente, sem nada explicando.
✅ Agora, nos dois cadastros: a cópia local voltou a ser o que ela sempre foi, um atalho. Se o navegador recusar, o sistema segue: mostra a lista, deixa salvar, manda a alteração pro servidor e publica o resumo pros aplicativos do mesmo jeito. O aviso vermelho não aparece mais nesse caso — quem avisa é a barra de sincronização, com "Sem espaço no navegador — limpe os dados do site", que é o recado certo, porque é isso que resolve.
🛡️ O que NÃO mudou: a trava que bloqueia o salvar quando a leitura falha de verdade (servidor fora do ar, internet caída) continua igual, inclusive tentando de novo antes de bloquear. Ela existe pra não gravar cadastro em cima de uma leitura que não veio, e continua de pé.
💡 No seu Mac: limpar os dados do site no Safari devolve o espaço. Enquanto não limpar, o sistema funciona normalmente — só não guarda a cópia de reserva, então cada abertura baixa tudo de novo.
É o mesmo conserto da v2.37.360/361, que na época salvou a carteira de pedidos. Caixas e clientes têm código próprio, escrito antes daquilo, e tinham ficado de fora.
🧹 Apagou a caixa do estoque e ela voltava? Agora fica apagada.
🔍 O que estava acontecendo: você apertou o ✕ (remover sem expedir) na KININO CX 44 às 00:17 e ela reapareceu às 03:04 — quase 3 horas depois. Apertou três vezes, voltou três vezes.
🧩 Por quê: a marca de "não trazer de volta" existia desde agosto, mas era conferida só num dos dois caminhos que repõem a linha. O outro punha a caixa de volta sem perguntar nada.
✅ Agora a pergunta é feita por quem realmente cria a linha — então vale para os dois caminhos, e para qualquer um que apareça no futuro.
↩️ E ganhou desfazer: se você apertou o ✕ sem querer, é só mandar o palete voltar pelo ↩️ Estornar — isso apaga a marca e a caixa volta. Antes não havia como voltar atrás.
🛡️ O que NÃO mudou: caixa que ninguém apagou continua aparecendo normalmente; linha que já existe não é duplicada; e pedido que saiu inteiro continua fora do estoque.
🏷️ Agora dá pra saber, num comando, se o servidor está atualizado.
🔍 O que aconteceu hoje: o servidor foi reiniciado, mas o código dele não tinha sido atualizado até a última versão. Resultado: o preço novo já entrava (parte nova funcionando) e a caixa tirada da ficha continuava aparecendo no link do cliente (parte que faltava). Descobrir isso levou meia hora de investigação, cruzando horários do histórico.
✅ Agora o servidor diz a versão dele. Se o número que ele responde for menor que o do sistema, ele está atrasado — e aí não adianta reiniciar: precisa atualizar o código antes.
🛠️ Recado pro Luan: reiniciar não é atualizar. O certo é puxar o código novo e reiniciar — só o pm2 restart mantém a versão velha rodando.
Não muda nada no seu dia a dia: é uma ferramenta de conferir, pra esse tipo de dúvida não custar meia hora de novo.
🚪 A última porta do "Carregado" ganhou trava.
🔍 O que estava acontecendo: existem três lugares no sistema que marcam um pedido como Carregado. Dois conferem antes. O terceiro — o app da Expedição, quando o expedidor finaliza a carga — marcava direto, sem conferir nada. Foi por essa porta que o FK GRUPO 19403 virou Carregado com 1.400 de 2.000: a Grampeadeira não tinha terminado, sobraram 789 caixas cortadas paradas, e o próprio "Carregado" ainda escondia o botão que resolvia.
✅ Agora: ao fechar a carga, a doca faz a mesma pergunta que o PCP — o que embarcou cobre o pedido? Se não cobre, o pedido continua "pronto p/ carregar" e o expedidor é avisado na tela, com o número: "1.400 de 2.000 cx".
🧩 A régua passou a morar num lugar só (o mesmo arquivo que a doca e o PCP já carregavam). Duas cópias fariam as duas telas discordarem do mesmo pedido — que é como esses problemas nascem.
🚚 A carga não muda em nada: ela fecha igual, o romaneio sai igual e a baixa dos paletes no estoque é a mesma. O que deixa de acontecer é só o pedido ser dado por carregado antes da hora.
⚠️ Quem decide depois é o PCP: quando o pedido realmente fechar, ele vira Carregado sozinho — lá o sistema tem a conta completa (sabe se sobrou trabalho na etapa de fechamento; o tablet não sabe). Ou seja, a doca erra pro lado de não afirmar.
🛡️ O que NÃO mudou: perda de produção normal (embarcou 98% ou mais) continua virando Carregado na hora; baixa manual do estoque continua não contando como embarque; e pedido sem quantidade cadastrada não é travado.
🔄 A ficha do Desenvolvimento agora se confere com o orçamento sozinha.
🔍 O que estava acontecendo: você corrigiu a CX 06 FRITO no orçamento (130 → 120 mm, R$ 1,868 → R$ 1,860) e o Desenvolvimento continuou mostrando os números velhos — e o link do cliente também, na medida.
🧩 Por quê: a correção da versão anterior fazia a mudança descer na hora de salvar o orçamento. Só que o que já estava desatualizado não tinha por onde voltar: a única saída era alguém reabrir o orçamento e salvar de novo — e não dá pra adivinhar isso.
✅ Agora: ao abrir a ficha no Desenvolvimento, o sistema confere com o orçamento e traz o que mudou na hora, dizendo na tela o que atualizou. Sem reabrir orçamento, sem salvar de novo.
🔗 É a mesma conta do salvar, no mesmo lugar — a ficha não pode dizer uma coisa ao abrir e outra ao salvar. E a mesma trava vale: caixa que já virou pedido nunca é tocada, e a tela avisa que ela ficou pra trás.
👁 No link do cliente: a medida passa a sair certa junto (ele já mostrava o preço novo, porque lê o orçamento de verdade).
⚠️ Duas coisas ainda dependem do reinício do servidor (tarefa do Luan, sem migração): o “Unitário” escrito na ficha interna, e a caixa que você tirou da ficha parar de aparecer pro cliente. Depois do reinício, os dois entram sozinhos.
Medido na ficha da JESSE: nenhuma das caixas tinha sido tocada pela correção anterior — por isso ela não chegava.
🧹 O Estoque PA estava contando palete que não existe — e a Expedição carregava por esse número.
🔍 O que você viu: o FK GRUPO 19403 aparecendo com 36 paletes no PA quando só tem 6; a KININO CX 44 dizendo "ficaram pra trás 3" quando ficou 1. Não era erro de conta da tela: o estoque tinha mesmo as linhas repetidas.
📊 Medido no servidor em 27/08: 21 linhas para 11 pedidos — 10 sobrando e 23.378 caixas que não existem. Repetido em três pedidos: FK GRUPO 19403 (5 cópias), TANGARA 03 FLOPS 46 (5 cópias) e KININO CX 44 (3 cópias).
🧩 Por quê: o Estoque PA é gravado no servidor como uma lista inteira. Quando um PC ainda não recebeu a linha que outro criou, ele cria a dele — e as duas ficam. Existia um botão 🧹 pra limpar isso na mão, mas ninguém roda, e as cópias voltavam sozinhas.
✅ Agora a limpeza é automática, na chegada: todo aparelho já recebe a lista sem cópias, então o número certo aparece na hora — no sistema e no app da Expedição. E a primeira gravação de qualquer PC já cura o servidor pra todo mundo.
🛡️ Nada de estoque real se perde: quando há cópias, fica a de maior quantidade; empatou, a que tem mais paletes gravados; empatou de novo, a mais antiga — pra a data de "pronto desde" não rejuvenescer. E entrada manual não é tocada (ela pode repetir de propósito).
O botão 🧹 continua onde estava, agora usando a mesma regra da limpeza automática.
🏷️ O número do lote não repete mais — era ele que estava embaralhando o estoque.
🔍 O que estava acontecendo: no FK GRUPO · 19403 os lotes da Grampeadeira saíram 1, 2, 3, 4… e o seguinte nasceu 1 outra vez. Com isso os 6 paletes novos ganharam os mesmos códigos de 3 paletes que já tinham embarcado.
🧨 O estrago que isso fez: a etiqueta imprimiu o "lote 1 inteiro" e falou em 9 paletes quando eram 6; o Estoque PA leu 3 dos novos como "já saiu" e marcou 343 cx / 3 paletes no lugar de 763 / 6; e na doca a Expedição ia recusar a bipagem como "já bipado".
🧩 Por quê: a única memória do número do lote eram os paletes carimbados na tela do operador — e o fim de turno limpa essa lista. Sem ela o contador via zero e começava do 1. A proteção que existe pra isso só era buscada dentro da pergunta da etiqueta, atrás de condições que não têm nada a ver com lote.
✅ Agora: o número do lote tem uma lembrança que só cresce, gravada na hora em que o lote é fechado. Não depende mais da lista de paletes nem da pergunta da etiqueta. E não volta nem depois de anular — o número do lote anulado já foi impresso em etiqueta, e reusar colidiria com papel que está no chão da fábrica.
⚠️ O que NÃO mudou: o primeiro lote de um pedido continua sendo 1; o "continuar no mesmo lote" quando a etiqueta não saiu continua igual; e a numeração dos paletes dentro do lote segue como sempre.
Este conserto impede novos casos. Os números que já ficaram errados no 19403 são acerto de dado, feito à parte.
🔁 O pedido que a Grampeadeira não terminou sumia da fábrica — agora dá pra trazer de volta.
🔍 O que estava acontecendo: no pedido FK GRUPO · 19403 a Slotter entregou 2.189 caixas e a Grampeadeira grampeou 1.400, em dois lotes. Os 10 paletes saíram no caminhão e o pedido virou Carregado — com 789 caixas cortadas paradas no galpão e nada na tela pra resolver: o pedido não aparecia mais na Grampeadeira, e o botão de reabrir também não aparecia.
🧩 Por quê: quando o operador usa "🖨️ imprimir prontos e continuar", a etiqueta sai, o lote é registrado e a etapa fica aberta de propósito — ele vai continuar depois. Só que o botão ↩️ Reabrir só aparecia em etapa marcada como concluída, e essa nunca foi. E a trava que deveria ter impedido o "Carregado" com meio pedido pergunta pro mesmo lugar — então os dois ficaram cegos juntos.
✅ Agora: se o pedido já foi dado por pronto (ou carregado) e ainda tem caixa cortada esperando o fechamento, aparece o ↩️ Reabrir Grampeadeira · terminar 789. Um clique devolve o pedido pra máquina — a produção já lançada e os paletes continuam do jeito que estão, nada é apagado.
🛡️ E a trava passou a enxergar: pedido nessa situação não vira mais "Carregado" sozinho — o sistema avisa na tela quantas caixas faltam e em qual máquina.
⚠️ O que NÃO mudou: pedido em produção continua sem botão (é o normal — o operador está com ele na mão); pedido Entregue nunca reabre; e quando o fechamento foi dividido entre Coladeira e Grampeadeira o sistema não chuta — prefere não oferecer nada a mandar grampear caixa que já foi colada.
Ainda em aberto: quem marca o pedido como "Carregado" ao fechar a carga no app da Expedição não passa por essa trava — é por ali que este pedido escapou. Fica pra você decidir se quer que ela valha lá também.
🗑️ Tirar UMA caixa da ficha do Desenvolvimento — e renomear.
🔍 O que estava acontecendo: a ficha da JESSE (ORC-0010) ficou com a mesma caixa duas vezes — CX 05 JESSE (a de 06/08, com as fotos, a arte, a amostra e a aprovação do Everton) e CX 05 ASSADO (a de hoje, vazia): mesma medida, mesma qualidade, mesma cor, mesmo preço. E a CX 06 FRITO ficou com um espaço a mais no nome.
🧩 Por que ninguém conseguia arrumar: a ficha só tinha o 🗑️ Excluir da proposta inteira. Ou você apagava as caixas boas junto, ou convivia com a cópia.
✅ Agora cada caixa tem os seus dois botões: ✏️ renomear e 🗑️ tirar da ficha.
🔒 Tirar NÃO apaga nada. A caixa continua ali, riscada, dizendo quem tirou e quando, com ↩️ trazer de volta a qualquer hora — fotos, arte e amostras seguem guardadas com ela. É o mesmo caminho da anulação de registro e da Lixeira de pedidos.
👁 Quem para de ver: a caixa tirada sai da conta de caixas, do funil, da cobrança de “falta o orçamento”, do app do Desenvolvimento, da fila de virar pedido e do link do cliente.
🛡️ O que ele nunca faz: caixa que já virou pedido não sai nem marcada (o pedido ficaria órfão na produção); caixa com foto, arte, amostra ou aprovação avisa o que está pendurado nela antes de perguntar; e nome vazio não grava.
⚠️ O link do cliente precisa do reinício do servidor (tarefa do Luan) para parar de mostrar a caixa tirada — e a própria tela avisa isso na hora de tirar, em vez de deixar você achar que o cliente já parou de ver.
Na ficha da JESSE: tire a CX 05 ASSADO (a vazia) e renomeie a CX 06 FRITO. A caixa com a amostra e a aprovação é a que fica.
🔁 Mexeu no orçamento, muda em todo lugar.
🔍 O que estava acontecendo: o cliente aprovou com uma ressalva — a CX 06 FRITO saiu de 130 pra 120 de altura. Você mudou no orçamento, e o link do cliente e o Desenvolvimento continuaram mostrando 130 e o preço antigo.
🧩 Por quê: a caixa do Desenvolvimento é uma cópia, tirada no dia em que ela foi trazida do orçamento — e nada nunca a reescrevia. O link do cliente até lia o orçamento de verdade, mas reencontrava a linha dele pelo nome + as medidas. Mudar a medida é justamente o que quebra essa procura: ou seja, a única alteração que mais precisava chegar no cliente era a que nunca chegava.
✅ Agora: ao salvar o orçamento, a mudança desce sozinha pro Desenvolvimento, pro link do cliente e pro app do vendedor — medida, qualidade, cores e preço. E o sistema conta na tela o que mudou em cada caixa.
🔗 As duas pontas ficam amarradas: a linha do orçamento passa a guardar qual caixa ela é lá no Desenvolvimento, e a caixa guarda qual linha ela é aqui. Depois disso, pode mudar medida, qualidade e nome de uma vez que elas continuam se achando.
🛡️ O que ele NUNCA faz: não encosta em caixa que já virou pedido (ali acabou a negociação — e avisa que não mexeu); não apaga o que o Desenvolvimento já sabia (orçamento sem cores não zera as cores da caixa; clichê e faca lançados na mão continuam); e não chuta: se a mesma caixa aparece duas vezes e não dá pra saber qual é qual, ele não mexe e diz isso.
📋 Registro interno (só nosso, o cliente não vê): a caixa do Desenvolvimento passa a mostrar o que veio do orçamento — "Medida: 450 × 240 × 130 mm → 450 × 240 × 120 mm", quando e por quem. E o Histórico de preço do orçamento, que já guardava o preço, passou a guardar também medida, qualidade e cores.
⚠️ Uma parte precisa do reinício do servidor (tarefa do Luan): o preço de caixa que já está com o cliente. Enquanto não reiniciam, medida, qualidade e cores já mudam normalmente — e o sistema avisa qual preço ficou faltando, em vez de dizer que atualizou.
O documento que sai pro cliente continua exatamente como era; o que mudou é ele estar sempre atualizado.
🔀 Duas fichas do mesmo orçamento no Desenvolvimento — agora dá pra juntar numa só.
🔍 O que estava acontecendo: o orçamento da JESSE foi trazido pro Desenvolvimento em 06/08 e virou uma ficha. Depois você acrescentou uma caixa no mesmo orçamento e trouxe de novo — e nasceu uma segunda ficha, do zero. O trabalho ficou partido: numa estavam a arte, a amostra, o link e a aprovação do cliente; na outra, as duas caixas novas e mais nada.
📄 E por que apareceu um “10” que não existe na lista de orçamentos: até a v2.37.199 a ficha do Desenvolvimento tirava um número próprio em vez de usar o do orçamento. A ficha de 06/08 nasceu ORC-0010 vinda do orçamento nº 0009 — está escrito nela: “Puxado do orçamento nº 0009”. O 10 nunca foi um orçamento, era o número da ficha. É por isso que o link dela aparece amarrado ao orçamento 9.
🔀 O que tem de novo: botão 🔀 Juntar em outra dentro da ficha. Você escolhe pra onde vai e ele leva tudo: as caixas com arte, amostra, fotos e as aprovações do cliente, o histórico inteiro e o link do cliente — que continua valendo, sem precisar mandar endereço novo.
🔒 Nada é apagado. A ficha de onde saiu continua lá, marcada com o destino, e cada linha do histórico chega no lugar novo com o texto original — é o retrato do que aconteceu. Só junta ficha do mesmo cliente: misturar aprovação de um com caixa de outro é recusado.
⚠️ Precisa do reinício do servidor (tarefa do Luan) pra funcionar. Enquanto não reiniciam, o botão avisa isso e não mexe em nada.
Ainda em aberto: trazer o mesmo orçamento duas vezes continua criando ficha nova. O próximo passo é ele reconhecer a ficha que já existe e só acrescentar a caixa que faltava.
📱 Agora, quando o celular bloqueia a janela de impressão, o sistema imprime do mesmo jeito — e avisa.
🚨 Solicitação de Compra (Almoxarifado JP Embalagens): se o navegador bloqueasse a janela — o normal no iPhone e comum no Android — o código quebrava e não imprimia nada, sem avisar ninguém. A pessoa clicava e achava que tinha mandado.
🚨 Cronograma do dia e da semana: a ordem de imprimir era dada tarde demais. Quando o documento ficava pronto rápido, a impressão simplesmente não acontecia — sem erro na tela. No iPhone era onde mais pegava.
✅ Agora os dois tentam a janela, depois imprimem por dentro do app, e por último baixam o arquivo pra você abrir — avisando em cada passo.
🖨️ Orçamento do cliente, portal e folha de peças: ganharam o tamanho de papel definido (antes quem escolhia era a impressora, cada uma de um jeito) e passaram a imprimir os fundos coloridos.
📋 Com esta, os 21 documentos do sistema foram revisados — a impressão do sistema inteiro passou pela mesma régua.
📊 Os relatórios pararam de sair com o cabeçalho invisível.
🔍 O que estava acontecendo: nos relatórios de Pedidos, Entregas, Curva ABC e Eficiência, o título de cada grupo é letra branca sobre uma tarja escura. O navegador imprime sem os fundos coloridos a não ser que a gente mande — e ninguém tinha mandado. No papel a tarja sumia e o título do grupo saía branco no branco, ou seja, invisível.
🔴 A linha do pedido atrasado (que é vermelha na tela) também perdia o destaque e virava uma linha comum no meio das outras. As tarjas de situação sumiam junto.
✅ Agora os quatro imprimem com as cores certas.
🖼️ E a logo: antes o sistema contava 200 milésimos e mandava imprimir. Em rede lenta, o relatório saía sem a logo. Agora ele espera a imagem e as letras carregarem — no máximo o necessário, sem travar.
📋 Com isso, dos 21 documentos do sistema, 13 já saem iguais em computador, iPhone e Android. Faltam os defeitos menores.
🚚 O romaneio do motorista agora sai igual em qualquer máquina.
🔍 O que estava acontecendo: a folha do romaneio pedia as letras da marca, mas não carregava nenhuma delas. Cada aparelho trocava pela letra dele — Windows por uma, Mac por outra, celular por outra. O mesmo romaneio saía com letra diferente, número de largura diferente e linhas quebrando em lugares diferentes conforme quem imprimia.
✅ Agora a folha carrega as letras certas e espera elas chegarem antes de imprimir. Se a internet estiver ruim, espera no máximo 2 segundos e imprime assim mesmo — nunca trava.
🖼️ A logo também: antes o sistema contava até 350 milésimos e mandava imprimir. Em rede lenta, o papel que vai com o motorista saía sem a logo. Agora ele espera a imagem carregar.
📱 No celular: se o navegador bloqueasse a janela, a impressão de reserva era feita numa caixinha de tamanho zero — que não desenha nada. Saía em branco, ou saía a tela do sistema no lugar do romaneio, e ninguém era avisado — com o número do romaneio já gravado no servidor. Agora funciona e avisa.
📐 E o papel: a folha passou a dizer que é A4 em pé. Sem isso, quem escolhia o tamanho era a impressora, e cada uma escolhia de um jeito.
📋 Ainda faltam os relatórios que imprimem o fundo escuro do sistema (Pedidos, Entregas, Curva ABC e Eficiência).
🖨️ As etiquetas pararam de sair em branco no papel.
🏷️ Etiquetas do Almoxarifado e da Bobina: a tarja de cima é colorida com letra branca em cima, e ninguém tinha mandado o navegador imprimir os fundos. No papel a cor sumia e sobrava branco no branco — a etiqueta saía sem o nome do cliente e sem o aviso TOCO. Numa bobina, perder o "TOCO" é a empilhadeira levar um rolo pela metade achando que é inteiro.
📄 Também saíam folhas em branco a mais no fim de cada impressão, porque elas imprimiam a tela do app junto.
🏷️ Etiqueta de amostra (Desenvolvimento): quem apertasse Ctrl+P com a etiqueta na tela recebia folha em branco. Eram duas causas somadas, e nenhuma sozinha explicava — precisei medir as quatro combinações no navegador pra achar.
✅ Agora as três montam uma folha própria, no mesmo formato da etiqueta de palete — a única que já saía igual em todo aparelho.
📱 E se o navegador bloquear a janela (comum no celular), o sistema imprime por dentro do app e avisa; se nem isso der, baixa o arquivo pra você abrir. Antes, nesses casos, não saía nada e ninguém era avisado.
🔧 Por baixo: a receita da etiqueta de palete virou um arquivo só, que todo documento novo vai usar. Assim as impressões nascem iguais em vez de cada uma ter a sua regra.
📋 Ainda faltam os relatórios que imprimem o fundo escuro e o romaneio com letra diferente em cada máquina — vêm em seguida.
🖨️ O laudo agora sai igual em qualquer computador.
🔍 O que estava acontecendo: o laudo se encaixava na folha medindo o tamanho da janela que abria, e não o tamanho do papel. Ele media numa largura e imprimia em outra — por isso o mesmo laudo saía de um jeito no Windows e de outro no Mac. E a sobra de papel embaixo era de menos de 2 milímetros: qualquer diferença mínima entre os dois sistemas jogava o conteúdo pra fora.
✅ Agora a folha é medida em milímetro (o que o papel entende), e sobra 7 milímetros embaixo. Medido: o resultado ficou idêntico com a janela larga, média e estreita.
📏 De onde veio a receita: da etiqueta de palete, que é a única que já saía igual em tudo — computador, iPhone e Android. Ela desenha em milímetro e sai um pouco menor que a folha, de propósito.
⚠️ Aviso honesto: aqui no Mac o laudo sempre saiu inteiro, de todo jeito que testei — não consegui repetir o corte. O que foi consertado é a fragilidade que explica por que ele quebrava aí. Se sair errado de novo, me manda uma foto da folha.
📋 Vem mais: a varredura achou outros 6 documentos que saem errado (etiquetas que somem no papel, romaneio com letra diferente em cada máquina, relatórios que imprimem o fundo escuro). Vão ser consertados em seguida.
🕐 O preço do orçamento não some mais. Trocou 2,030 por 1,990 porque o cliente pediu? A versão anterior fica guardada inteira — igual a um romaneio já emitido — e dá pra reabrir e reimprimir o documento exatamente como o cliente recebeu. Na lista, o orçamento revisado ganha o selo rev 2 e o botão 🕐 Histórico de preço, com o que mudou, quando, por quem e o motivo. Casa com o pedido de revisão de preço do vendedor: ao abrir o ✗️ Editar pra ajustar, o preço que já foi passado está na tela.
💲 Histórico de preço no cadastro do cliente. Bloco novo com a linha do tempo de cada caixa: quanto já custou, desde quando, e se o preço veio do orçamento, do cadastro, do pedido ou de um reajuste.
📈 Reajuste por cliente, sem mexer no que já foi negociado. No cadastro do cliente dá pra lançar “+7% a partir de tal dia”. A partir daí pedido novo dele já nasce com o aumento, mostrando a conta (“2,030 do cadastro + 7% = 2,172”). E nada do que já existe muda: o preço do cadastro continua o mesmo, a programação já lançada segue no preço combinado e orçamento já enviado vira pedido no preço que foi enviado. Desligar o reajuste devolve tudo na hora.
🔒 Preço negociado de um pedido fica travado — nem reajuste, nem preço novo no cadastro, nem reescolher a caixa na edição encostam nele.
🐛 Histórico de romaneios abria desatualizado. Ele só era puxado do servidor na hora de emitir um romaneio; quem apenas abria a tela via o que estava guardado naquele computador — num PC que nunca emitiu nada, a lista aparecia vazia com tudo salvo no servidor. Agora abrir a tela puxa antes de desenhar.
O histórico de preço é interno: o orçamento que sai pro cliente (PDF, WhatsApp, e-mail) continua exatamente como era. Vindo do MTX.
🚚 Agora o sistema sabe COMO CADA CLIENTE RECEBE — e conta pra quem precisa, na hora certa. Uns só aceitam sider, uns não têm empilhadeira, uns exigem palete PBR de no máximo 1,80 m, uns só recebem com hora marcada até as 16h30. Isso morava na cabeça do vendedor e do motorista.
📝 Quem preenche é o vendedor, na visita, pelo app dele: botão 🚚 Recebimento no cartão do cliente, em 6 etapas com botões grandes (quase nada se digita). Dá pra parar no meio — o que ele já respondeu fica guardado no celular e ele continua depois. No sistema central está tudo também, em Cadastros → Clientes → 🚚 Recebimento.
📄 O romaneio que vai com o motorista passou a sair com o quadro “Como este cliente recebe”: horário e dia, hora de corte, com quem agendar, tipo de palete e altura, quem descarrega, EPI da portaria e a observação da entrega. O motorista chega sabendo.
📦 O operador vê na máquina como o palete tem que ser — e o app avisa em laranja quando o cadastro da caixa não bate com o que o cliente exige (“o cliente só recebe palete 1000×1200 e esta caixa está cadastrada com 1100×1100”). O mesmo aviso aparece no cadastro da caixa, onde dá pra corrigir.
🚚 Na doca, ao montar a carga, aparece a janela de recebimento de cada cliente e o aviso quando a chegada prevista cai fora: “chega ~17:10 e o cliente recebe até 16:30 — ligue antes de sair”.
📏 Caixa nova de cliente com perfil já nasce com o palete dele (medida, altura e filme) no lugar do padrão fixo da casa. Caixa que já existe não muda sozinha.
✅ Nada foi tirado e nada trava. Cliente sem o perfil preenchido continua exatamente como hoje: o romaneio sai igual, o operador não vê aviso nenhum e a carga fecha do mesmo jeito. Tudo é opcional — campo em branco quer dizer “ainda não perguntei”, e não vira linha em lugar nenhum. E o 🕔 Horário de recebimento que já existia no cadastro continua lá: ele é quem pré-preenche a janela.
🧹 Agora TODO cadastro que você apaga some de verdade.
🔍 Faltavam 7 telas: 🤝 Vendedores, 🔬 Laudistas, 🚛 Caminhões, 📄 Papéis, 🔩 Peças, 🏭 Terceiros e 📦 Expedidores. Em todas, o ✕ tirava o cadastro da tela e ele voltava quando a página abria de novo — o mesmo defeito que o motorista tinha (v2.37.566).
✅ Agora as sete mandam o servidor apagar de verdade, e o cadastro só some da tela depois que o servidor confirma.
⚠️ Se der problema (internet caiu), o cadastro fica na lista com um aviso vermelho explicando — nunca mais some sem ter sumido de verdade.
📦 Expedidores tinha DUAS telas de excluir, cada uma com o mesmo defeito. As duas foram consertadas.
👍 Manutentores e Encarregados já estavam certos — não foram mexidos. Eles guardam os dados de outro jeito, em que apagar da lista já funcionava.
🔧 Por baixo: a conta de apagar passou a morar num lugar só, em vez de virar 8 cópias — cópia de conta sempre acaba divergindo com o tempo. O motorista foi junto pro mesmo lugar.
🔧 Pro Luan: nada a fazer — as rotas de apagar já estavam no ar.
📅 Agora dá pra dizer QUANDO a carga vai ser entregue. Até aqui a carga só tinha a hora em que o caminhão foi carregado — e era ESSA data que ia no WhatsApp do motorista, parecendo a data da entrega. Quem carrega hoje e entrega na segunda não tinha onde escrever isso.
✅ Ao começar a carga — no app da Expedição e aqui no sistema — o campo 📅 Data da entrega passou a ser obrigatório. Embaixo do campo a tela diz o dia da semana ("segunda-feira") e avisa quando a data escolhida já passou.
📍 A data aparece em quatro lugares, sempre a mesma:
• no WhatsApp do motorista — agora separado: "Carregado em..." e "Entregar em..."
• no app do motorista, em destaque em cima da carga dele
• no painel 🚛 Expedição ao vivo, do lado da placa (amarelo quando é pra outro dia)
• no romaneio, na linha "📅 Entrega prevista" — o papel que vai com o caminhão e o cliente assina
🔁 Quem começa a carga pelo ▶ da escala não digita nada: a data vem da viagem que o escritório já programou.
⚠️ Carga antiga não muda — quem não tem a data não ganha uma inventada: a linha simplesmente não sai, e a 2ª via de um romaneio velho continua igual à 1ª.
📅 A segunda via de um romaneio novo repete a MESMA data da primeira — o papel do cliente nunca muda sozinho.
✅ Não precisa do Luan: é só tela.
🚚 Agora o motorista que você apaga some de verdade — e não volta mais.
🔍 O que estava acontecendo: o ✕ da tela de Motoristas tirava ele da lista só na sua tela. O “salvar” que ia pro servidor só sabe cadastrar e atualizar — ele nunca soube apagar. Então o motorista sumia na hora e voltava assim que a página era aberta de novo.
✅ Agora o ✕ manda o servidor apagar o cadastro de verdade, e só tira da tela depois que o servidor confirma.
⚠️ Se der problema (internet caiu, servidor não respondeu), ele continua na lista e aparece um aviso vermelho explicando — nunca mais some sem ter sumido de verdade.
🧹 Serve pros cadastros repetidos que estavam presos: “Gildo Lima” (o sem placa, que era cópia do GILDO LIMA DOS SANTOS) e “maycon”.
📌 O motorista sai do cadastro, mas o nome dele continua nas cargas, romaneios e viagens já feitas — nada do histórico se perde.
🔧 Pro Luan: nada a fazer — a rota de apagar já estava no ar, só ninguém chamava ela.
🛡️ Nenhum computador apaga mais uma caixa do estoque que ele não sabe explicar. Este é o conserto da raiz do sumiço das caixas — os anteriores tratavam o sintoma.
🔍 A raiz: o estoque era gravado como lista inteira. Quem salvasse por último mandava — então um computador com o sistema numa versão antiga recebia as linhas novas, apagava com o código velho e regravava por cima, pra todo mundo.
✅ Agora, antes de salvar, o sistema confere o que está no servidor. Toda caixa que o servidor tem e este computador não tem precisa de explicação pra sumir:
• saiu tudo pelo registro de paletes → some, normal
• você tirou pelo ✕ → some, normal
• qualquer outro caso → a caixa volta pro que vai ser salvo
🌱 O que isso muda na prática: mesmo que sobre algum computador desatualizado por aí, ele não consegue mais apagar o estoque dos outros.
⚠️ Se a internet falhar na hora de conferir, o sistema salva do mesmo jeito — uma proteção que trava não pode virar "o estoque parou de sincronizar".
📦 Protege as caixas do PA. Chapas e histórico de movimentação seguem como antes.
✅ Não precisa do Luan: é só tela.
♻️ A caixa da entrega parcelada volta pro estoque SOZINHA — não depende mais de clicar no Recalcular.
🔍 Por que precisou: você clicou no ♻️ Recalcular, as 6 linhas apareceram (00:19) e sumiram 9 minutos depois. Investiguei: os 6 movimentos continuaram no histórico e só as caixas sumiram — isso é a assinatura de remoção pelo código, não de alguém gravando por cima.
💻 Quem estava apagando: algum computador com o sistema aberto numa versão mais antiga (anterior à v2.37.555). Ele recebe a linha nova, apaga com o código velho e regrava — e como o estoque é gravado como lista inteira, isso vale pra todos. Medido rodando o mesmo caso em três versões: a 2.37.554 apaga, a 2.37.559 e a atual mantêm.
✅ Agora: a conferência roda sozinha a cada atualização da tela. Se alguém apagar, ela volta em segundos — você não precisa ficar clicando.
❌ E o ✕ continua mandando: quando você tira uma linha pelo ✕ ("remover sem expedir"), ela fica marcada como tirada de propósito e NÃO volta. A marca guarda quem tirou e quando, e vale em todos os computadores.
🔄 Mesmo assim, vale atualizar todos os computadores que usam o sistema (F5 até a versão 2.37.561): enquanto um ficar na versão velha, ele continua apagando e a tela fica piscando entre um estado e outro.
✅ Não precisa do Luan: é só tela.
🚚 Fechar a carga não marca mais como "Carregado" um pedido que quase não embarcou. Você viu no TANGARA 23848 · 03 FLOPS 46: 15 paletes prontos, a carga levou 1 (701 cx de 10.012) e o pedido ficou CARREGADO com 14 paletes na fábrica.
🔍 O que acontecia: ao fechar a carga, o app conferia quantos paletes daquele pedido estavam no Estoque PA pra saber se levou tudo. Só que, quando o pedido não tinha linha no estoque, ele lia essa falta de informação como "levou tudo" e marcava carregado.
🔗 Uma falha alimentava a outra: esse pedido estava fora do Estoque PA justamente por causa do problema da entrega em 2 remessas (corrigido nas v2.37.555 e 558). Sem a linha, a carga "concluiu" o pedido sozinha.
✅ Agora: o pedido só vira Carregado quando dá pra provar que a carga levou todos os paletes disponíveis. Não dando pra provar, o sistema não afirma nada — e ninguém fica pra trás: quem fecha nesse caso é a conferência do PCP, que compara caixa por caixa o que saiu em carga com o que foi produzido.
📦 Carregado parcialmente continua igual: enquanto sobrar palete, o pedido segue "Pronto p/ carregar" com o selo 🚚 CARREGADO PARCIALMENTE · X de Y paletes, e vira Carregado sozinho quando o último palete embarcar. Com esta correção o selo passa a aparecer também nesses casos — antes o pedido já tinha virado "Carregado" e o selo não era desenhado.
⚠️ Nada mudou pro carregamento normal: carga que leva todos os paletes do pedido continua fechando na hora, igual a sempre. Levar mais que o disponível (sobra de lote) também continua fechando.
🔄 Pros pedidos que já ficaram assim: clique ♻️ Recalcular no Estoque (traz os paletes de volta) e mude o status pra Pronto p/ carregar. Ele não volta pra Carregado sozinho — a conferência do PCP exige que o que saiu alcance o produzido.
✅ Não precisa do Luan: é só tela.
📝 O que muda a cada remessa agora tem lugar na nota — sem mexer no cadastro da caixa. Lote, data de fabricação, observação daquela entrega: tudo isso vai num campo do item, e o cadastro do produto continua parado onde está.
📌 Onde aparece: na janela da pré-nota entrou "Informações adicionais do item", logo abaixo da descrição. O que você escrever ali sai embaixo do nome do produto na nota — que é exatamente onde o DANFE imprime.
🔍 Por que assim, e não mudando o nome do produto: das três formas que existem, esta (infAdProd) é a recomendada. Mexer no nome atrapalha o cliente, que confere o produto contra o pedido; e o grupo de rastreabilidade formal exige lote, quantidade e data juntos — fica pra quando a JP precisar disso.
🔒 Duas travas contra o defeito clássico ("o campo existe na tela mas não sai no papel"): um teste confere que o texto aparece impresso embaixo da descrição, e outro confere que o que você digita chega mesmo na nota — guardar num canto e não levar é a outra metade do problema.
⚠️ Passou de 500 letras, ele RECUSA em vez de cortar calado: a nota tem esse limite, e meia informação é pior que nenhuma — o cliente leria "Lote ABC-12" achando que é o lote inteiro.
⚠️ Enquanto o Luan não atualizar o banco, quem escrever nesse campo recebe um aviso pedindo a atualização — em vez de a nota ser gravada sem o texto, calada. Quem não usa o campo não sente nada.
🔧 Teste novo: 10 casos e 7 mutações, todas acusadas (tests/inf-ad-prod.test.mjs). Suíte: 206 testes, 0 falhas, com 48 rodados contra um PostgreSQL de verdade.
⚠️ Precisa do Luan: npm run db:migrate (migration 043) e pm2 restart all.
♻️ O ♻️ Recalcular do Estoque agora TRAZ DE VOLTA o lote que tinha ficado de fora. Complemento da v2.37.555 — e é ele que resolve o caso da TCHETTO · 01 MOLHO REFOGADO que você apontou.
🔍 Por que o conserto anterior não bastou: a v2.37.555 destravou o caminho, mas ele só funciona quando chega apontamento novo do operador. O lote de 25/08 já tinha chegado antes da correção, foi recusado uma vez e não chega de novo — ficava preso pra sempre, porque nenhum caminho o trazia de volta (o ♻️ só conferia as linhas que já existem, e nunca criava).
✅ Agora: vai em Estoque e clica em ♻️ Recalcular. A linha 01 MOLHO REFOGADO · 4.401 cx · 4 paletes aparece, com os paletes de verdade — as etiquetas já impressas continuam bipando. Fica um lançamento no histórico: "Lote novo depois de uma carga".
🔢 A conta: foram produzidas 9.656 caixas; 5.255 (5 paletes) já saíram na carga de 20/08; sobram 4.401 em 4 paletes. Conferi contra o registro de saídas real, palete por palete.
🔒 Só volta o que tem prova de que sobrou: o sistema exige que parte do pedido tenha saído (registrada palete a palete) e que ainda haja palete sem saída. Pedido que embarcou inteiro não volta, e nada aparece com número chutado.
👆 Só no botão, nunca sozinho: a varredura roda quando você clica em ♻️ Recalcular. Assim, linha que você tirou de propósito no ✕ não volta sozinha no meio do dia.
🛠️ Nada foi apagado: as outras linhas do estoque ficam exatamente como estão.
✅ Não precisa do Luan: é só tela.
🔓 O app do vendedor deixou de pedir a senha o tempo todo — e ganhou um botão de emergência.
🔍 Por que pedia tanto: o acesso do app nasceu com o mesmo prazo do login do computador do PCP — 2 horas. Só que o computador fica aberto o dia inteiro, e o celular do vendedor vai pro bolso. Na prática, da noite pro dia seguinte o acesso já tinha vencido, e era isso que fazia a tela de orçamentos aparecer vazia (o que consertei ontem à noite na v2.37.554).
✅ Agora: o app só pede a senha de novo se ficar uma semana inteira sem ser aberto. Usando normalmente, ele pede uma vez por mês.
🔒 E se um celular for perdido ou roubado: em 📋 Cadastros ▸ 🤝 Vendedores, cada linha ganhou o botão 🔒. Ele corta na hora o acesso daquele vendedor em todos os aparelhos — quem estiver com o app aberto passa a pedir a senha.
⚠️ O 🔒 NÃO apaga nada: o cadastro do vendedor fica intacto e ele volta a entrar com a senha dele. O que morre é o acesso que está aberto no aparelho. Trocar a senha no cadastro não faz isso — o acesso já aberto continuaria valendo; é justamente pra isso que o botão existe.
⚠️ Se der 0 aparelhos, a tela diz isso — quer dizer que naquele momento ninguém estava com o app aberto no nome dele. Nunca aparece "cortei" sem ter cortado.
🔒 O login do sistema no computador não mudou: continua caindo com 2 horas parado, como sempre. São prazos separados de propósito — o risco de cada um é diferente.
🧪 Teste novo com 33 conferências e 6 mutações (tests/vendedor-derrubar-acesso.test.mjs), inclusive uma que acusa se alguém esticar o login do PC junto.
⚠️ Este PRECISA do Luan: mexe no servidor. Peça o reinício da API (não precisa de migration). Até ele reiniciar, o prazo velho continua valendo e o botão 🔒 avisa que o servidor ainda não foi atualizado.
↩️ Agora dá pra DESFAZER uma baixa. Na tela de Baixa, cada pedido da lista de baixados ganhou o botão ↩️ Desfazer. Antes aquela lista era só leitura: quem desse baixa por engano — ou num pedido que ainda tinha o que produzir — ficava com ele fora da carteira ativa pra sempre.
💰 O dinheiro sai junto, e é isso que evita cobrar duas vezes. A baixa gera as contas a receber; se elas ficassem lá e você desse baixa de novo, a mesma nota entraria DUAS VEZES na previsão de caixa. Agora as contas daquela nota saem do Financeiro junto — e só as daquela nota.
🔒 Nada é apagado. A baixa desfeita fica guardada dentro do pedido (quem baixou, quando, quantas caixas, quem desfez) junto com a cópia das contas, e o evento aparece na 📜 Vida do pedido. O registro é gravado antes de qualquer coisa ser mexida.
⛔ Conta já PAGA barra tudo. Se alguma parcela daquela nota já foi baixada em dinheiro, o sistema não desfaz e explica por quê: o dinheiro entrou e sumir com a linha faria o extrato não fechar. Nada é tocado nesse caso.
📍 Foi o FORTYS 23961 que trouxe isto: baixado em 25/08 com 10.000 cx tendo embarcado 4.134, e ainda faltando 5.866 pra produzir. Agora dá pra desfazer a baixa, reprogramar e fechar o ciclo direito no fim.
🔒 Na dúvida, não faz: se o Financeiro não tiver carregado na tela, a baixa não é desfeita — mexer na baixa sem conseguir mexer no dinheiro é o pior dos dois mundos.
🧪 20 conferências e 7 mutações, todas acusadas (tests/desfazer-baixa.test.mjs), rodando o código real da carteira e do financeiro. Suíte inteira: 178 passam, 0 falham.
✅ Não precisa do Luan: é só tela.
📦 Entrega em duas remessas: o 2º lote voltou a entrar no Estoque PA. Você viu no TCHETTO 23920 · 01 MOLHO REFOGADO: os paletes estavam prontos e etiquetados, e o estoque não mostrava nada.
🔍 O que aconteceu: em 20/08 a Coladeira fechou 5.255 cx (5 paletes) e a carga saiu — carga finalizada. Em 25/08 ela colou o resto: 4.401 cx em 4 paletes, com as etiquetas já impressas. Essas 4.401 caixas nunca entraram no estoque.
🔒 Por quê: quando um pedido aparece numa carga finalizada, o sistema o marcava como "já expedido" pra sempre. As duas portas que colocam caixa no PA barravam por causa disso, antes de fazer qualquer conta — e ainda apagavam a linha. Não sobrava nem movimento no histórico: a caixa simplesmente não existia pro sistema.
✅ O conserto: agora a pergunta certa é "sobrou palete que ainda não saiu?". Se sobrou, a caixa entra no PA normalmente. Essa régua já existia desde a v2.37.138 na porta que tira do estoque — as duas portas que põem tinham ficado pra trás. Agora as três usam a mesma conta.
🏷️ As etiquetas já impressas continuam valendo — e isso é o mais importante. A caixa entra com os paletes de verdade do registro (lote 2, paletes 1 a 4), com a mesma identidade que está no QR. A Expedição bipa e dá baixa normalmente.
⚠️ NÃO use a Entrada manual pra isso. Ela cria uma linha solta, sem ligação com o pedido e com paletes sem identidade — as etiquetas impressas não casariam e o palete não biparia na doca. Sua desconfiança estava certa: seria mesmo um lançamento diferente.
🛠️ Nada foi apagado e nada volta indevidamente: pedido que saiu inteiro continua fora do estoque exatamente como antes, e na dúvida o sistema não traz caixa de volta. Os status Carregado e Entregue continuam barrando como sempre.
🔄 O caso do TCHETTO se resolve sozinho: na próxima leitura dos registros a linha entra com as 4.401 cx e os 4 paletes.
✅ Não precisa do Luan: é só tela.
⏱ O app do vendedor parou de dizer que não tem orçamento quando na verdade não conseguiu carregar. A Tatiane abriu o app dela e a aba 📄 Orçam. estava vazia, escrito "você ainda não enviou nenhum orçamento" — com três orçamentos esperando o aceite dela, um de R$ 110.295,42. Pelo seu acesso de administrador, os mesmos três apareciam.
🔍 Não era cache. O app já busca tudo direto do banco, sem guardar nada — ele relê o servidor a cada 4 segundos. O que acontecia é que o acesso dela tinha vencido: por segurança, o crachá do app morre depois de umas horas com o app fechado. Três coisas dependem dele — orçamentos, solicitações e comissão — e o servidor passou a recusar. Só que o app não avisava: mostrava a tela vazia. Os clientes continuavam aparecendo (esses não dependem do crachá), e por isso parecia que estava tudo bem.
✅ Agora a tela fala: quando o acesso vence, aparece "⏱ Sua sessão expirou" com o botão 🔑 Entrar de novo — no topo do app e dentro da aba de orçamentos. É um toque e a senha; os clientes conhecidos continuam na lista.
🔒 Só o "acesso vencido" mostra isso. Wifi ruim, internet caindo ou servidor fora não mandam ninguém pro login — seria trocar um problema por outro. E ninguém é expulso no meio de um orçamento: o aviso fica, e você entra quando quiser.
🧪 Teste novo com 24 conferências e 4 mutações (tests/vendedor-sessao-expirada.test.mjs).
✅ Não precisa do Luan: é só tela.
🔄 O botão 🔄 Reprogramar também volta a aparecer em pedido "Carregado" que não embarcou tudo. Você pediu pra arrumar o FORTYS 23961 e descobri que ele não se resolve pelo Reabrir — ali falta cortar E colar, não só colar.
📋 O 23961 hoje: pedido de 10.000, o Corte e Vinco cortou 4.152, a Coladeira colou 4.134 e os 6 paletes embarcaram — tudo em 24/08. Faltam 5.866 caixas, e a chapa lançada (6.000) só cobre 1.848 delas.
🚪 O defeito era o mesmo da v2.37.551, numa TERCEIRA porta que eu não tinha contado. Os três botões do pedido — ↩️ Reabrir fechamento, ↩️ Reabrir corte e 🔄 Reprogramar — tinham a mesma regra escrita à mão: "pedido carregado não volta". Consertei duas e deixei a terceira, que era justamente a que serve pro 23961.
✅ Agora a pergunta é uma só, num lugar só, e vale pros três: pedido carregado volta pra produção quando o que embarcou não cobre o pedido. Pedido ENTREGUE continua sem voltar.
📍 No 23961, o botão certo é o 🔄 Reprogramar (roxo, dentro do pedido): ele mostra Pedido 10.000 · Feito 4.134 · Falta 5.866 e deixa você lançar a chapa do que falta. A produção já feita continua contando e nada é apagado.
⚠️ Confira o faturamento desse pedido: ele está marcado como faturado em 25/08 com 10.000 cx, mas só 4.134 embarcaram. Não mexi nisso — é decisão sua.
🧪 Teste ampliado: 31 conferências e 10 mutações, todas acusadas (tests/carregado-so-com-o-pedido-fechado.test.mjs), rodando a linha real do modal. Suíte inteira: 176 passam, 0 falham.
✅ Não precisa do Luan: é só tela.
🖱️ A roda do mouse passou a rolar o bloco que está embaixo dela. Você pediu: "queria que o scroll do mouse funcionasse igual do menu lateral, que funcionasse no bloco de pedidos; não está funcionando, só funciona em cima da barra".
🔍 O que estava acontecendo: os três lugares que você apontou — Dashboard ▸ PEDIDOS, Dashboard ▸ CRONOGRAMA e a lista da Carteira — são caixas que rolam por dentro. Quando o mouse está em cima de uma delas e ela não tem pra onde ir (o eixo está travado, ou já chegou no fim), o giro morre ali em vez de passar a vez pra página. Sobrava levar o mouse até a barrinha de rolagem. O menu lateral funciona porque ele rola de verdade, então o giro tem onde cair.
✅ O conserto: agora o sistema confere se o giro fez alguma coisa. Fez — ele não encosta em nada. Não fez — ele completa: rola o bloco, e se o bloco já acabou, rola a página. É conserto que se desliga sozinho onde já funcionava (Chrome, notebook com trackpad, celular): lá a conta sempre dá "já rolou".
🔒 O que ele nunca faz: não cancela o giro (a regra da casa que já derrubou a rolagem do Mac uma vez, em agosto), não mexe em Ctrl/⌘ + roda (que é o zoom do navegador), não inventa rolagem quando tudo já está no topo, e não atrapalha o gesto de lado nem a pinça no tablet.
⚠️ Se você sair da aba e voltar depois, o giro antigo é jogado fora — a tela não dá pulo. E a roda não trava: tem um segundo relógio de segurança.
🧪 Teste novo com 24 conferências e 6 mutações (tests/roda-do-mouse.test.mjs).
📋 Por enquanto vale no sistema. Se você quiser nos apps (Operador, Qualidade, Expedição…), é só me pedir — é uma linha em cada.
✅ Não precisa do Luan: é só tela.
↩️ O botão de reabrir agora aparece direto no pedido que está "Carregado" sem ter embarcado tudo. Complemento da v2.37.549: lá eu impedi o pedido de virar Carregado com caixa pronta esperando a colagem, mas os pedidos que já estavam presos continuavam sem o botão — você tinha que mudar o status pra "Em produção" na mão antes de abrir.
🔎 Por que ele se escondia: a regra era "pedido carregado já saiu da fábrica, não reabre". Certa pro caso normal — e foi ela que fechou o beco do 23920: o sistema carregou o pedido cedo demais e sumiu justamente o botão que resolvia.
✅ Agora: pedido Carregado mostra o botão só quando o que embarcou não cobre o pedido. É a mesma conta da trava da 549 — senão o sistema barraria o carregamento e esconderia o botão ao mesmo tempo. E o confirm avisa antes: "este pedido está como CARREGADO com 5.255 de 10.000 cx embarcadas — ele VOLTA PRA PRODUÇÃO".
🔒 Pedido ENTREGUE nunca reabre — ali a mercadoria chegou no cliente. E pedido carregado que embarcou tudo continua sem botão nenhum, igual a hoje.
📋 Hoje isso vale pra mais 2 pedidos além do 23920: ALPACK 23532 (faltam 49) e FORTYS 23961 (embarcou 4.134 de 10.000). O botão só aparece — quem decide é você.
🔒 Nada foi apagado e nenhum pedido mudou sozinho. Na dúvida (conta indisponível na tela), o pedido carregado não oferece reabrir — o comportamento de antes.
🧪 Teste ampliado: 28 conferências e 9 mutações, todas acusadas (tests/carregado-so-com-o-pedido-fechado.test.mjs) — inclusive "deixar pedido entregue reabrir" e "carregado reabrir sem olhar quanto embarcou". Suíte inteira: 175 passam, 0 falham.
✅ Não precisa do Luan: é só tela.
⏸ A tela de Produtividade dizia 914,5h de máquina parada onde o real é 53,8h — dezessete vezes mais. Quem abrisse o ranking via o Miller com 641,2h parado; o verdadeiro é 29,6h. O Fabricio aparecia com 194,5h contra 5,5h reais.
🔍 De onde vinha o número: uma única parada de "esperando chapa" que ficou correndo de 03/07 até 15/07 — 290 horas e 19 minutos, porque ninguém apertou ▶ Retomar produção. E ela está gravada em dois registros do mesmo pedido (23393, DEUSA ALIMENTOS), então entrava duas vezes: 580 horas de uma só vez. A prova de que está errada não é chute — a parada dura mais que o registro que a contém (o registro rodou das 07:06 às 13:44).
✅ O conserto já existia e faltava ligar aqui. A conta de "dá pra confiar no tempo desta parada?" nasceu na v2.37.545 e já valia no 📊 gráfico, no 🎯 OEE e na ficha do operador — a tela de Produtividade, justamente a que mostra tempo parado por pessoa, tinha ficado de fora. Agora ela usa a mesma conta, no mesmo arquivo: duas contas fariam esta tela discordar das outras três.
👀 Some da conta, nunca da tela: no ranking aparece um ⏸4 amarelinho do lado do tempo parado (passe o mouse pra ler o porquê), e na tela individual do operador sai escrito "4 paradas esquecidas (611h40) fora da conta". Número certo que esconde botão esquecido na máquina é pior que número errado.
🔒 Nada foi apagado nem mudado no histórico: as paradas continuam gravadas do jeito que estão, com a hora de início original. Só deixaram de entrar na soma (REGRA ZERO).
🧪 Teste: 12 conferências e 6 mutações, todas acusadas (tests/produtividade-parada-esquecida.test.mjs) — inclusive "voltar a somar tudo", "filtrar mas não mostrar o que saiu" e "fazer conta própria em vez de usar a que já existe". Rodei com a parada real de 290h do seu banco.
✅ Não precisa do Luan: é só tela.
🚚 "Saiu 5 mil de 10 mil, o pedido está como carregado e a Coladeira não vê pra terminar de colar." O 23920 TCHETTO · 01 MOLHO REFOGADO: a Slotter imprimiu as 10.000, a Coladeira colou 5.255 e os 5 paletes embarcaram. Ficaram 4.745 caixas já impressas, paradas na fábrica.
🕵️ Por que o pedido virou "Carregado" com metade: o sistema comparava o que saiu no caminhão com o que a Coladeira tinha feito (5.255) — nunca com o tamanho do pedido (10.000). Saíram os 5 paletes, ou seja, tudo o que existia → "saiu tudo". As 4.745 que faltam nunca chegaram a virar palete, então não entravam na conta.
🔒 E o "Carregado" trancava a porta do conserto. O botão que resolve — "↩️ Reabrir Coladeira · terminar 4.745" — é escondido de propósito em pedido já carregado ("saiu da fábrica, não reabre"). Com o pedido carregado cedo demais, sumia justamente o botão que faltava. E no app da Coladeira o pedido ficava invisível: a marca de "concluído" vale 7 dias e a aba ✅ Concluídos só mostra as últimas 18 horas.
✅ O que mudou (1): enquanto sobrar caixa pronta esperando a máquina de fechamento, o pedido não vira "Carregado" sozinho — e a tela avisa com o número na frente: "saíram 5.255 de 10.000 cx e faltam 4.745 pra Coladeira terminar". A pergunta é a mesma do botão de reabrir, de propósito: se o botão apareceria, o pedido não vira carregado.
✅ O que mudou (2): o ↩️ Reabrir passou a liberar de verdade a máquina seguinte. Antes, neste pedido, ele devolvia o pedido pra Coladeira mas ela batia em "⏳ AGUARDANDO SLOTTER" e não conseguia pegar — o conserto do PCP não chegava na fábrica.
🔕 Não morde o dia a dia. Perda na colagem é rotina (a Slotter entrega 10.000, a Coladeira lança 9.900 e as 100 viram refugo): esse pedido continua virando Carregado, porque saiu 99% do que o cliente pediu. Só segura com as duas provas juntas — sobrou trabalho parado E o que saiu ficou abaixo do pedido. Pedido sem etapa de colagem, sobra de produção e baixa manual no PA continuam exatamente como eram.
🔒 Nada foi apagado e nenhum pedido mudou de status sozinho. Na dúvida (conta indisponível na tela, pedido sem quantidade), o sistema faz o de sempre.
🧪 22 conferências e 6 mutações, todas acusadas, rodando o código real dos três lados — sistema, estoque e app do operador (tests/carregado-so-com-o-pedido-fechado.test.mjs). Suíte inteira: 173 passam, 0 falham.
✅ Não precisa do Luan: é só tela.
⏸ Sete paradas ficaram abertas para sempre — e quem pegasse aquele pedido de volta abria o app com a faixa vermelha MÁQUINA PARADA e o cronômetro correndo desde JUNHO. São paradas em que ninguém apertou ▶ Retomar produção e que nunca receberam hora de fim: um "tomar café" de 19/06, uma refeição de 30/06, manutenções de 08/07 e 20/08 e mais um "falta de programação" na Slotter, além de duas na Máq. A Corte e Vinco.
🔎 Por que ninguém tinha visto: elas valem 0 minuto (sem hora de fim não há duração), então não apareciam em soma nenhuma. Mas TODA tela que pergunta "tem parada rolando nessa máquina?" procurava simplesmente a primeira parada sem hora de fim — e achava ELAS. Só não estourava na cara de ninguém porque aqueles apontamentos já estavam encerrados; bastava um operador pegar o pedido de volta.
✅ A regra agora: parada aberta há mais de 12 horas não é máquina parada — é o mesmo botão Retomar que ninguém apertou (o maior turno da casa tem 9h48). Ela deixa de abrir a faixa vermelha, deixa de virar alerta no 🔔 sino, deixa de pintar "Parado" na carteira e deixa de ancorar barra no cronograma.
🗣️ E o operador é AVISADO: ao pegar o pedido de volta ele lê "⏸ Uma parada ficou aberta (🔧 Manutenção) — não estou contando o tempo". Sem esse aviso, o conserto viraria um problema escondido — e o botão continuaria sendo esquecido na máquina.
🔒 Continuo sem tocar em dado gravado: as sete paradas seguem no histórico exatamente como estão, com a hora de início original. Fechá-las exigiria inventar uma hora de fim que ninguém sabe — e isso eu não faço (REGRA ZERO).
🧮 A conta é a MESMA da v2.37.545, no mesmo arquivo (js/66-parada-esquecida.js), agora lida por 5 telas: Mural, sino de alertas, carteira, cronograma e o app do operador — que passou a carregar o módulo. Todas com reserva: sem o arquivo, tudo volta a se comportar como antes.
🧪 Teste ampliado: 45 conferências e 11 mutações, todas acusadas (tests/parada-esquecida.test.mjs) — inclusive "a parada velha voltar a abrir a faixa" e "engolir a parada de agora junto com as velhas". Rodei com as 7 paradas reais do seu banco.
✅ Não precisa do Luan: é só tela.
🔧 "Pulei o ajuste e o app travou — tive que fechar e entrar de novo." Achei. O operador abria o pedido, tocava em Pular ajuste, tocava em ▶ Iniciar produção agora e não acontecia nada: sem aviso, sem erro, sem tela nova. Fechando o app e entrando de novo, funcionava.
🕵️ O defeito não estava na produção — estava em como o app ESCONDE as janelinhas. A janela de perdas do ajuste e a de configurar paletização aparecem por um comando; e dois lugares do app apagavam elas de um jeito que o comando de aparecer não conseguia mais desfazer. Dali em diante o app ficava esperando você tocar numa janela que nunca ia aparecer na tela — parecia travado, mas ele estava só esperando.
🌙 O gatilho acontecia todo dia: quando o turno fecha sozinho, o app esconde essas janelinhas antes de voltar pro login. Aí o operador do turno seguinte entrava no mesmo tablet, sem fechar o app — e pegava o problema pronto. O mesmo acontecia depois do PCP reiniciar um pedido do zero com o tablet aberto nele.
✅ O que mudou: esconder e mostrar janela passou a ser feito num lugar só, do jeito certo. E mostrar agora limpa o que ficou pra trás — então até um tablet que já estivesse assim volta ao normal sozinho, sem precisar fechar o app.
🔒 Nada foi apagado e nada mudou de comportamento. As janelinhas continuam iguais, os avisos de fim de turno continuam iguais, a paletização continua igual. O que mudou é só a janela voltar a aparecer.
🧪 Teste novo que roda no navegador de verdade (o defeito era de tela, não de conta) com 7 conferências e 6 mutações, todas acusadas (tests/modal-nao-abria-e-travava-producao.test.mjs). Rodado também contra a versão que estava no ar: ele aponta as duas linhas culpadas.
✅ Não precisa do Luan: é só tela.
📄 A arte da caixa voltou a aparecer no app do operador. Você avisou que a arte da CX 12 FLOPS PERFUMADO (TANGARA) não abria, mas a da 04 FLOPS 70, do mesmo cliente, abria normal.
🔍 O que estava acontecendo: a arte sempre esteve certa no cadastro (perfumado flops.pdf, 205 KB, layout inteiro e legível — eu abri o arquivo pra conferir). O problema era o app não achar a caixa: a ficha dizia "Caixa ainda não está no PC" e, sem a caixa, o botão da arte nem chega a aparecer.
🔗 Por que ele não achava: o pedido guarda um vínculo direto com a caixa, mas esse vínculo não estava sendo enviado pro tablet. Sem ele, o app tinha que casar pelo nome — e o nome do pedido vem do Sectra enquanto o do cadastro é escrito à mão:
pedido: "12 FLOPS PERFUMADO 46,2" × cadastro: "CX 12 FLOPS PERFUMADO"
Não bate, e o app — com razão — prefere não chutar caixa nenhuma a mostrar a arte errada.
🧩 Por que a "04 FLOPS 70" funcionava: nela o código do pedido é igual ao do cadastro, então o casamento por nome dava conta e o vínculo nem fazia falta. Era isso que fazia parecer "defeito só nessa caixa".
📌 O conserto: o vínculo da caixa passou a viajar junto com o pedido pro app. Agora o tablet acha a caixa pelo vínculo antes de tentar pelo nome.
📊 Quantas caixas isso afetava: conferi os 258 pedidos que têm vínculo cadastrado — 3 estavam nessa situação (os 3 com arte cadastrada), e o único vivo na carteira agora é justamente o 12 FLOPS PERFUMADO. Nos outros 255, o vínculo aponta pra exatamente a mesma caixa que o nome já achava — ou seja, nada muda pra quem já funcionava.
⚠️ O tablet precisa receber a lista nova: a correção vale pros pedidos que o sistema publicar daqui pra frente. Se a arte não aparecer na hora, toque em 🔄 Carregar pedidos no app do operador.
🛠️ Nada foi apagado nem trocado: nenhuma arte, nenhum cadastro e nenhum pedido foram alterados — só passou a ser enviado um campo que já existia e ficava pra trás.
✅ Não precisa do Luan: é só tela.
⏸ Achei 13 paradas que ficaram com o cronômetro correndo — e elas estavam mentindo em TODO relatório de parada. Quando ninguém aperta ▶ Retomar produção, a parada não fecha. A campeã: um "esperando chapa" que começou 03/07 às 10:06 e só fechou 15/07 às 12:25 — 290 horas, dentro de um registro que rodou das 07:06 às 13:44. E ela está gravada em DOIS registros, ou seja contava 580 horas.
📉 O tamanho do estrago, medido no seu banco: o tempo total de parada da fábrica saía 1.010,9 h. O verdadeiro é 70,0 h. Quatorze vezes maior — e não era só a Slotter: tem parada esquecida na Corte e Vinco (165h), na Coladeira (50h) e na Grampeadeira (20h) também. No OEE isso é pior ainda: uma parada maior que a janela do registro zerava a Disponibilidade daquela máquina.
🔎 Como o sistema sabe que o número está errado — sem chutar: a parada dura mais que o próprio registro que a contém. Um registro que rodou 6h38 não pode ter dentro dele uma parada de 290 horas; é contradição, não opinião. E, por cima disso, uma parada que passa de 12 horas já atravessou o turno inteiro (o maior turno da casa tem 9h48), então ninguém estava lá pra apertar o botão.
👁️ Ela sai da conta, mas NÃO some da tela. Embaixo dos números do gráfico de paradas nasceu um aviso amarelo listando cada uma: quanto marcou, em que máquina, quem estava, qual pedido e por que não entrou. Sumir com o problema seria esconder um botão que continua sendo esquecido no chão de fábrica.
🔒 NÃO mexi em nenhum dado gravado. Nenhuma parada foi apagada, encurtada ou reescrita — o registro continua no histórico exatamente como está, com o horário original legível (REGRA ZERO). O que mudou é só a LEITURA: gráfico de paradas, OEE e Ficha do Operador passaram a perguntar "esse tempo cabe no registro?" antes de somar. Na ficha, a parada esquecida aparece marcada com ⏸ e vale 0 min.
🧮 A conta mora num arquivo só (js/66-parada-esquecida.js), usada pelas três telas: duas cópias divergiriam e o gráfico diria um número e o OEE outro. Se o arquivo não carregar, tudo volta a contar como antes — nunca corta parada por acidente.
🧪 Teste novo com 28 conferências e 7 mutações, todas acusadas (tests/parada-esquecida.test.mjs) — inclusive "cortar parada de verdade" e "chutar até agora numa parada sem fim". Ele roda contra os casos REAIS da Slotter.
✅ Não precisa do Luan: é só tela.
🛑 Puxar palete e abastecimento viraram BOTÃO no app do operador. Antes, pra registrar essas duas paradas o operador tinha que apertar "🔹 Outro motivo" e digitar na mão.
🔎 Por que justo estas duas: conferi a lista de paradas da Máq. B Slotter que você me mandou — 127 paradas, e 84 delas foram digitadas na mão. Só "puxando palete" (42, contando quem escreveu "puxar palete") e "abastecimento" (21) somam 63 — praticamente metade de todas as paradas da máquina.
📊 O ganho é no relatório. Digitado na mão, cada um escrevia de um jeito ("puxando palete", "puxar palete", "abastecimento e puxando palete") e o sistema não somava junto: tudo caía no balaio "Outro". Agora cada um vira uma linha só, com nome e tempo próprios no gráfico de paradas, no Mural, na Ficha do Operador e no OEE.
📦📥 Onde ficaram: os dois entraram no fim da grade, logo acima do "🔹 Outro motivo" — nenhum botão que já existia mudou de lugar, pra ninguém apertar errado por costume. O "🔹 Outro motivo" continua lá pra tudo que não tem botão.
⚠️ Não mudei nenhuma conta: essas duas paradas continuam pesando exatamente como hoje (entram como espera, fora do tempo de produção) — não mexi em eficiência, cronograma nem OEE. Se você quiser que elas passem a contar de outro jeito, é uma decisão sua e é só me pedir.
🗂️ As paradas antigas ficam como estão: o que já foi escrito na mão continua no histórico com o texto que o operador digitou. Não mexi em nada do passado.
✅ Não precisa do Luan: é só tela.
🔐 O login do Noel voltou a mostrar Caminhões e Motoristas. Você marcou na tela 🔐 Acessos que o perfil EXPEDIÇÃO pode ver 🚛 Caminhões e 🚚 Motoristas (e 🧑✈️ Expedidores só pro Noel) — e no login dele não aparecia nada disso.
🔍 Por que acontecia: um pedaço de código antigo, de antes da tela de Acessos existir, mandava esconder as telas de Cadastros de todo mundo que não fosse Admin ou PCP. Como ele era o último a falar, passava por cima do que você tinha marcado.
🧩 O estrago era maior do que parecia: 🚚 Motoristas e 🧑✈️ Expedidores eram escondidos à força; 🚛 Caminhões nem estava naquela lista, mas ficava inalcançável, porque o botão do módulo 📋 Cadastros sumia junto. E pelo mesmo pedaço o perfil ficava sem 🚛 Carregar Caminhão, sem 📜 Histórico de Cargas e sem o botão do módulo 🚚 Expedição.
✅ O conserto: esse pedaço antigo saiu. Quem manda agora é só a tela 🔐 Acessos — o que você marcar lá (por perfil ou por pessoa) é o que aparece.
⚠️ Muda também, e você aprovou: o Financeiro passa a enxergar 👥 Clientes, 🏭 Fornecedores e 💳 Condições de pagamento; o Desenvolvimento, 👥 Clientes, 📦 Caixas, 🧾 Micro e 📐 Chapas; o Vendedor, 👥 Clientes. São telas que o perfil deles já listava e que aquele pedaço antigo escondia. Não quer alguma? É um clique na 🔐 Acessos pra tirar.
🔒 Não abriu porta de graça: quem não tem a tela marcada continua sem ela — o Visualizador não ganhou cadastro nenhum, e o que está no "menos" do perfil da Expedição (Dashboard, Relatório, PCP) continua fechado. Admin e PCP saem idênticos.
📋 Encontrei mais três pedaços iguais e NÃO mexi (é outro assunto, me peça quando quiser): 📦 Estoque e 📈 Gráficos, 🎯 Produtividade e o botão 👷 Operadores também decidem por conta própria em vez de olhar a 🔐 Acessos.
🧪 Teste novo com 33 conferências e 6 mutações (tests/permissao-telas-perfil.test.mjs): ele roda o login de verdade, com a sua configuração de Acessos de verdade.
✅ Não precisa do Luan: é só tela.
🧾 O aviso vermelho de IPI na pré-nota sumiu — a resposta já estava no seu cadastro. A pré-nota dizia "o cadastro deste cliente não diz se ele tem IPI SUSPENSO" e saía tributada. O erro era meu: o sistema decide IPI pela carta de isenção desde sempre, e eu não tinha ligado isso na nota.
🔍 A regra da casa, que agora a nota usa: carta de isenção no prazo → não paga IPI. Sem carta → 15%. Conferi no seu cadastro real: 11 dos 42 clientes ativos têm carta válida (ATALAIA, DEUSA, JESSE, KININO, MITTO, NACON, SANTISA, TANGARA, TCHETTO, THINSOL, VIVIMAR) e nenhuma está vencida. Ou seja: os 42 têm resposta, e o aviso era nosso.
👁 A tela agora diz de onde veio a decisão, embaixo do cliente: "IPI não destacado — carta de isenção no prazo (válida até 15/06/2027)" ou "IPI tributado — este cliente não tem carta válida". Dá pra conferir sem abrir o cadastro.
🔐 Se alguém marcou na mão no cadastro, a mão ganha — decisão de pessoa vence conta automática.
⚠️ ACHADO IMPORTANTE, e ele mexe em dinheiro: escrever 0 no campo IPI do cadastro não isenta ninguém. A regra sempre foi "se o IPI do cadastro for MAIOR que zero, usa ele; senão, 15%" — então o 0 cai no padrão. 13 clientes ativos estão com 0 escrito e pagam 15% assim mesmo. Se algum deles deveria ser isento, o certo é anexar a carta, não escrever 0. Não mexi em nenhum — só estou te avisando.
🔧 Testes novos rodando a função REAL do sistema: 9 casos (tests/ipi-do-cliente.test.mjs) e 5 mutações, todas acusadas. Suíte: 182 testes, 0 falhas.
✅ Não precisa do Luan: é só tela.
📍 O código do município da nota fiscal, que faltava em TODOS os clientes, passou a sair sozinho. A NF-e exige o código do IBGE da cidade (7 dígitos) do emitente e do cliente. Fui conferir o seu cadastro: 0 de 42 clientes ativos tinham.
✅ Agora ele é descoberto na hora, a partir da cidade e do estado que já estão cadastrados. Medido no seu cadastro de verdade: 35 dos 42 já saem resolvidos, e os 7 que faltam são os que não têm cidade nenhuma preenchida — falta de cadastro, não do sistema.
📚 A tabela é a oficial do IBGE, com os 5.571 municípios do Brasil (conferida contra os totais conhecidos: SP 645, PR 399, MG 853). Código de município não se escreve de cabeça — errado é nota rejeitada.
🔍 Escreve "GARCA" e a tabela diz "Garça"? Casa do mesmo jeito — acento, maiúscula e pontuação não atrapalham. E "Bariri" procurado no RJ não acha nada: ele nunca pega um parecido de outro estado.
⚠️ Nada foi gravado no seu cadastro, de propósito: o código é descoberto na hora de fazer a nota. Assim não tem dado pra migrar nem pra apagar sem querer, e cidade corrigida já sai certa na nota seguinte. E quando não acha, fica vazio — nunca um município inventado.
🔧 Teste novo: 7 casos e 6 mutações, todas acusadas (tests/ibge-municipio.test.mjs) — inclusive "tabela pela metade" e "chutar um código quando não acha". Suíte: 173 testes, 0 falhas, com os 38 de banco rodados contra um PostgreSQL de verdade.
⚠️ Precisa do Luan: pm2 restart (é API). Não precisa de migration.
🧾 Numeração da nota fiscal — série, ambiente e "a partir de qual número". Em 🏢 Empresas → Editar entrou uma caixa nova. É o primeiro passo pra emitir de verdade: cada empresa passa a ter a sua sequência, e homologação (teste) conta separado da produção.
⚠️ A série tem que ser DIFERENTE da do Sectra. Se as duas usarem a mesma, sai número repetido — e aí ou a SEFAZ rejeita, ou o cliente recebe duas notas diferentes com o mesmo número.
🔒 A numeração só anda pra frente. Se você tentar começar num número que já saiu, o sistema recusa e diz qual foi o último. E se ele não conseguir descobrir qual foi o último, também recusa — na dúvida não mexe, porque aqui errar é nota duplicada.
🔑 O certificado digital NÃO entra aqui — nem pode. O arquivo .pfx, a senha dele e o token do provedor ficam no servidor, instalados por quem tem acesso a ele. Nesta tela vai só qual provedor, o nome da variável onde o token mora e a validade do certificado (pra o sistema avisar antes de vencer). Se alguém colar o token no campo do nome, a tela recusa e o servidor recusa também — os dois, porque tela velha guardada no aparelho continua mandando.
⚙️ "A partir de qual número" serve pra quem já emitiu por fora: a empresa que está na nota 5.000 começa daqui no 5.001. Ele é piso, nunca um contador que se escreve — quem manda continua sendo o maior já emitido + 1.
🔧 Salvar numeração é botão separado do "Salvar empresa": número fiscal não se mexe junto com endereço.
🔧 Testes novos: 10 casos e 7 mutações, todas acusadas (tests/numeracao-nfe.test.mjs). Suíte: 166 testes, 0 falhas, e os 38 de banco rodados contra um PostgreSQL de verdade.
⚠️ Precisa do Luan: mexi na API (pm2 restart). Não precisa de migration — as colunas já existem desde a 023.
🖨️ O espelho da pré-nota imprimia uma folha EM BRANCO — consertado. Você mandou imprimir o espelho da pré-nota Nº 6 e saiu papel vazio, com o título certo em cima.
🔍 O que era: a marca-d’água "SEM VALOR FISCAL" estava presa na tela (fixa), e continuava assim na hora de imprimir. O Safari imprime a folha em branco quando sobra um elemento fixo na impressão. No Chrome saía perfeito — por isso demorou a aparecer.
🔎 Como eu achei: gerei o papel de verdade aqui e olhei. No Chrome, impecável. Aí comparei com os documentos desta casa que imprimem bem há meses — romaneio, laudo, orçamento: todos chegam no papel sem nenhum elemento fixo (no romaneio o único fixo é a barra de botões, que some na impressão). O espelho era o único fora do padrão.
🔧 O conserto: a marca-d’água deixou de ser fixa — ela continua lá, atravessada, igualzinha. E o botão de imprimir passou a chamar a impressão do mesmo jeito que o romaneio chama.
⚠️ Aviso honesto: eu não consegui reproduzir o Safari aqui — o diagnóstico veio da diferença pros documentos que funcionam. Imprime uma vez e me diz se saiu.
🔧 Teste novo com 5 casos (tests/espelho-imprime.test.mjs): ele barra qualquer elemento fixo que sobre no papel, confere que a marca-d’água e o conteúdo continuam lá, e que o espelho segue sem chave de acesso e sem código de barras — ele nunca pode virar um DANFE de mentira. Provado: com a marca fixa de volta, o teste acusa.
✅ Não precisa do Luan: é só tela.
🔒 O sistema deixou você do lado de fora com ele inteiro guardado no seu Mac — consertado. Hoje a hospedagem barrou o nosso IP (aquela tela de "Verificação de segurança" com a palavra pra digitar) e o Safari mostrou tela de erro em vez do sistema.
🔍 Por que a cópia salva não apareceu: quando o app se atualiza sozinho, ele recarrega num endereço com a hora atual no fim (sistema.html?v=1787607546270) — um número diferente a cada vez. E a busca pela cópia guardada procurava o endereço exato: nunca achava nada, porque aquele endereço só existiu naquele segundo. Agora, quando a internet falha, a página procura ignorando esse número — e abre.
🛡️ Segunda trava, pra não acontecer coisa pior: a página de bloqueio da hospedagem responde “deu certo” em todo endereço — medi: até o arquivo de versão voltou como a tela do captcha. Do jeito que estava, ela seria guardada por cima do app, e depois de desbloquear você abriria o captcha guardado, sem entender por quê. Agora o app só guarda o que parece o nosso app. Quando não parece, ele serve a cópia boa — e a fábrica continua trabalhando.
⚠️ Uma coisa de propósito: se não houver cópia guardada, a tela de bloqueio aparece mesmo — senão ninguém veria a palavra pra digitar e o bloqueio nunca sairia.
🔧 Teste novo com 11 casos e 7 mutações, todas acusadas (tests/sw-parede-e-cache.test.mjs) — ele roda o arquivo de verdade num navegador de mentira, com a página de bloqueio real guardada como amostra. Duas falhas do próprio teste foram achadas pelas mutações e corrigidas.
✅ Não precisa do Luan: é só tela. Cada aparelho precisa abrir o sistema uma vez pra pegar a proteção nova.
🧾 O botão "Calcular e gravar" da pré-nota não fazia nada — consertado. Você clicou e a tela ficou parada, sem nem uma mensagem de erro. O defeito era meu, entrou ontem junto com o IPI suspenso.
🔍 O que estava acontecendo: a parte que GRAVA a pré-nota precisa olhar o cadastro do cliente (pra saber se ele tem IPI suspenso). Só que ela olhava uma informação que só existe na parte que ABRE a janela. Na hora de montar o que ia pro servidor, ela parava ali — e parava antes do trecho que mostra aviso na tela. Por isso o silêncio: nem gravava, nem reclamava.
🔧 O conserto são duas linhas: quem grava passou a ler o cadastro do cliente por conta própria. Nada mais mudou — a conta dos impostos, o espelho e a baixa continuam iguais.
✅ Agora tem teste que APERTA o botão. Os testes que existiam conferiam a conta, o selo e a escolha da empresa — nenhum clicava em gravar, e foi por isso que isso passou. O teste novo faz o caminho inteiro: abre a janela, aperta o botão e confere que a pré-nota saiu com a quantidade do romaneio, o CNPJ do cadastro e o IPI certo. 5 mutãncias testadas (inclusive o próprio defeito de ontem) e todas são acusadas.
⚠️ Um detalhe que ficou escrito: quando o cliente ainda não tem resposta sobre IPI suspenso, o sistema manda "não sei" — e não "cobra IPI". Quem decide isso é o servidor, que avisa e segue tributando. Chutar aqui já fez nota voltar devolvida.
✅ Não precisa do Luan: é só tela.
🚚 Um palete virado ao lado de um em pé — a sua ideia, olhando a planta da KININO. Você perguntou: "tem como colocar um palete virado? seria um de 1312 e um de 1000 que dá 2312". Dá sim, e o ganho é real.
📏 A conta: a CX 23 é 1.312 × 1.000 mm e o baú tem 2.400 de largura. Dois em pé ocupam 1.000 + 1.000 = 2.000, e cada fileira come 1.312 de comprimento. Um virado + um em pé dá 1.312 + 1.000 = 2.312 — e aí as duas faixas passam a andar em passos diferentes: 1.000 de um lado, 1.312 do outro. Na sua carga: os mesmos 12 lugares, mas em 7,00 m de baú em vez de 7,87 m.
🔍 O que estava travando: o sistema SEMPRE soube girar palete — ele testa as duas posições, uma por uma. Só que havia um atalho: "se já coube tudo, não precisa tentar de outro jeito". Isso vale pra quantidade, mas não pro comprimento: a segunda tentativa nunca rodava, e o desempate por "qual arrumação gasta menos baú" — que já existia no código — nunca era usado. O atalho saiu.
🎯 E resolveu o SEU primeiro problema de quebra: aquele vão de 43 cm no meio do baú do POWERDENT, que você circulou na foto, some sozinho agora — sem precisar do ✓ "Apertar o arranjo". A carga vai de 5,28 m para 4,77 m, com os mesmos 15 paletes.
📊 Medido em 500 cargas com a geometria real das 174 caixas cadastradas: 188 ficaram mais curtas (112 m no total, a maior economia foi 1,56 m), nenhuma levou menos palete e nenhuma ficou mais comprida. O cálculo passou de 32 para 43 milissegundos — ninguém sente.
⚠️ O que muda na doca: o plano passa a mandar virar alguns paletes, marcados com ↻ ao lado do nome. Acontece em mais ou menos 1 de cada 3 planos. A frente da carga fica em degrau — sem buraco: as duas faixas ficam encostadas, só terminam em pontos diferentes. Decisão sua, em 24/08/2026: sempre ligado.
🔧 Teste novo com 4 mutações (tests/carga-giro-misto.test.mjs) e o teste do ✓ Apertar o arranjo foi refeito: a fixture dele era justamente o caso do POWERDENT, que o motor agora resolve sozinho. 76 testes do sistema rodados, todos passando.
✅ Não precisa do Luan: é só tela.
🏢 Agora dá pra cadastrar as empresas que faturam — quantas você quiser. Apareceu o botão 🏢 Empresas ao lado do "Faturar por", no orçamento. Cadastra razão social, CNPJ, IE, endereço e o regime — e é o regime que decide como a nota sai: Presumido destaca ICMS e IPI; Simples usa CSOSN e recolhe no DAS. Os campos do Simples (anexo, CSOSN, % de crédito) só aparecem quando você escolhe Simples, pra ninguém preencher onde não vale.
🚫 Empresa não se apaga, se desativa: some da lista de escolha e as notas já emitidas continuam apontando pra ela.
🧾 E o cadastro do cliente ganhou o "IPI na nota fiscal". Quase metade das caixas da JP sai com IPI suspenso — conferi nas suas notas. Cobrar IPI de quem tem direito à suspensão faz a mercadoria voltar: aconteceu em março, a nota 25.088 foi devolvida e teve que ser reemitida.
🤔 São três respostas, não duas, e isso é de propósito: "cobra IPI", "IPI suspenso" e "não sei ainda". Enquanto estiver em "não sei", a nota sai cobrando (como sempre foi) mas avisa que ninguém decidiu isso. Prefiro que o sistema diga "não sei" a fingir que sabe — quem tem direito à suspensão quem diz é o contador.
Testado com o ciclo inteiro rodando: cliente → caixa → pedido → romaneio → pré-nota → espelho, com o mesmo pedido saindo nas três situações (venda, industrialização e IPI suspenso). E um defeito foi pego pelo próprio teste antes de subir: editar só o telefone de uma empresa estava apagando IE, município e UF.
⚠️ Precisa do Luan: pm2 restart all (a rota de cadastrar empresa é nova). A migration 042 do dia anterior também, se ainda não rodou.
🔍 Abri o banco do Sectra e conferi a pré-nota contra as suas 42 mil notas de verdade. Achei quatro coisas erradas — nenhuma delas chegou a cliente nenhum, porque a pré-nota é ensaio e não tem valor fiscal. Todas corrigidas.
🏭 A maior: o sistema tratava TUDO como venda. Mas quase metade do que a JP fatura é industrialização — quando o papel é do cliente e vocês só transformam. Nessas notas o ICMS e o IPI vão suspensos (a nota sai com zero), e o sistema estava colocando 18% de ICMS em cima. Agora ele sabe a diferença: venda sai com CFOP 5101/6101 e imposto normal; industrialização sai 5125/6125 com os dois suspensos. O PIS e o COFINS continuam sendo cobrados nas duas — conferi, porque zerar tudo teria sido errado.
🧾 O IPI da CHAPA é 3,25%, não 15%. Quem manda é o produto: caixa 15%, chapa 3,25%. E vocês vendem 5 chapas para cada caixa — com 15% nela, a nota cobraria mais de um milhão a mais em meio ano.
💵 O PIS e o COFINS estavam com as alíquotas erradas (0,65% e 3%); as suas notas usam 1,65% e 7,6%. Conferido em 6 mil itens.
📏 A unidade ficou em UN, como você decidiu — combinando com a quantidade em caixas. Detalhe traiçoeiro: se a unidade dissesse "milheiro" com a quantidade em caixas, o papel leria mil caixas como um milhão, e o valor total continuaria batendo. Ficou teste travando isso.
Cada número acima saiu da conta feita em cima das notas reais (valor ÷ base), não de rótulo, e foi reconferido por consulta direta antes de virar código. A venda continua reproduzindo a sua NF-e nº 25.718 centavo por centavo.
⚠️ Precisa do Luan: npm run db:migrate (migration 042) + pm2 restart all. Sem isso, as alíquotas novas não valem.
⚠️ Falta ainda: 47% das suas caixas saem com IPI suspenso e o sistema ainda não sabe disso — a regra de quem tem direito é do contador. Até lá, conferir esse campo antes de emitir.
📦 "Esse pedido da VIVA GRAFICA estava aparecendo carregamento parcial." Estava mesmo — e parou de aparecer por defeito. O pedido 23770 · 1 LITRO tem 3 paletes (1.051 + 1.051 + 970 = 3.072 cx), 1 só foi no caminhão (o palete 2, na carga do Jurandir, dia 22) e a tela passou a dizer "saiu tudo". Os outros 2 paletes — 2.021 caixas — continuam na fábrica.
🔍 Por que aconteceu: pra saber se saiu tudo, o sistema precisa de duas coisas: quantos paletes o lote TEM e quantos JÁ SAÍRAM. O "quantos tem" ele lia da linha do Estoque PA — e quando essa linha some, ele passava a usar o próprio número de paletes que saíram. Ou seja: 1 de 1 — sempre completo, por mais palete que tivesse ficado pra trás. O selo "carregado parcialmente" ficava impossível de aparecer.
✅ O conserto: o número certo nunca se perdeu — ele está gravado nos registros de produção, que é de onde o próprio recalcular do estoque remonta os paletes. Agora o sistema busca lá quando a linha do PA não está. O 23770 voltou a mostrar "🚚 CARREGADO PARCIALMENTE · 1 de 3 paletes · 1.051 cx".
🔒 E não inventa o contrário: se o sistema não conseguir saber o tamanho do lote, ele não chuta — diz só quantos paletes saíram, e não afirma nem "saiu tudo" nem "falta".
⚠️ Uma diferença de palavra que importa: "ainda no PA" é afirmação sobre estoque, e sem a linha do PA o estoque não tem nada daquele pedido. Nesses casos a tela passou a dizer "1 de 3 paletes já saíram" (o que o sistema realmente sabe) em vez de "2 de 3 ainda no PA" — porque o que faltou pode ser palete parado na fábrica ou palete que saiu numa baixa em bloco, sem bipar, e daqui os dois são iguais. Vale no card da Carteira, nas rodadas do pedido e na Vida da Caixa.
📊 Conferido no servidor (24/08/2026): 8 pedidos estavam com o total errado — VIVA GRAFICA, 2 do TCHETTO, 2 da TANGARA, FK GRUPO e 1 de teste. Nenhum perdeu um "saiu tudo" que estivesse certo. O selo volta só no VIVA GRAFICA: os outros já estão Entregues, e em pedido entregue o selo continua calado, como sempre foi. Teste com 16 mutações (tests/carregado-parcialmente.test.mjs); 71 testes do sistema rodados, todos passando.
✅ Não precisa do Luan: é só tela.
📏 No tablet do operador, a caixa que vai ABERTA mostrava METADE do palete. Quando você marca “📏 CAIXA VAI ABERTA” no cadastro, ela sai plana, sem colar: no palete cada uma tem uma espessura de onda, não duas. O sistema e o desenho do palete já contavam certo — a ficha do tablet não, e ela decidia só pelo setor Facão.
📋 Conferido no cadastro de verdade hoje: das 190 caixas, 6 estão marcadas como ABERTA — e as 6 estavam erradas na ficha:
DCX PARMEGIANE G e P · REVAL CX M — mostrava 7 camadas / 350 cx → agora 14 / 700
FK GRUPO 51900 — mostrava 10 camadas / 1.000 cx → agora 20 / 2.000
KININO CX 22 — mostrava 15 camadas / 750 cx → agora 30 / 1.500
📦 O estrago era prático: quando o operador ia montar o palete, o app já vinha com a caixa/palete pela metade preenchida (350 no lugar de 700) — palete montado na metade da altura, o dobro de paletes no caminhão. Agora ele vem com o número certo e a ficha explica por quê: “esta caixa vai ABERTA (não é colada) — no palete cada uma conta 1 espessura, não 2”.
⚠️ Nada muda pra caixa colada nem pra folha do Facão — continuam exatamente como estavam. ⚠️ Os números novos são os mesmos que o cadastro já tinha salvo, ou seja, a ficha passou a concordar com o sistema. 19 checagens e 6 mutações de teste (tests/ficha-operador-caixa-aberta.test.mjs).
✅ Não precisa do Luan: é só tela. ⚠️ Os tablets precisam abrir o app uma vez pra pegar esta versão.
📏 Agora dá pra dizer a espessura que a chapa TEM NO PALETE — e entra a camada que faltava. Você pôs 2.700 mm de altura pra caber 15 pacotes e o sistema só deixava 14. Pela onda BB ele conta 5,8 mm por chapa: 15 × 5,8 × 2 = 174 mm de pacote, e 15 pacotes seriam 2.610 + 150 do estrado = 2.760 mm — não fecha por 60 mm. Só que a chapa prensa quando os pacotes vão um em cima do outro: no palete montado ela mede menos do que no cadastro.
📍 Onde fica: Cadastros → Caixas → 8 · Paletização → campo “Espessura no palete (mm)”. Pondo 5,6, o pacote vira 168 mm e entram as 15 camadas — 900 caixas por palete no lugar de 840.
💡 É só pra caso específico, uma caixa de cada vez. Deixando o campo vazio nada muda: ele usa a espessura da onda, como sempre fez. Preencha só na caixa que precisa (é o que acontece na onda BB). Pra desfazer, apaga o campo.
⚠️ Vale SÓ na montagem do palete — chapa, peso, gramatura, orçamento e a onda no cadastro continuam com a espessura de sempre. ⚠️ Os três lugares que contam palete passam a dizer o mesmo número: a sugestão escrita, o desenho do palete e a ficha do operador (que mostra “espessura medida no palete: 5,6 mm”). ⚠️ Caixa marcada como ABERTA continua contando uma espessura, não duas. 26 checagens e 11 mutações de teste (tests/palete-espessura-ajuste.test.mjs).
✅ Não precisa do Luan: é só tela — o ajuste mora dentro do cadastro da caixa, sem mexer no banco.
🔧 O buraco no meio do baú: o conserto está pronto e vem DESLIGADO. Você circulou na planta um vão de 43 cm no meio da carga e perguntou se não dava pra pôr um palete ali. Não dava — nenhum palete tem menos de 1 m. Mas o vão não precisava existir.
🔍 Por que ele aparece: quando as duas fileiras do baú ficam com a frente desencontrada e o próximo palete é largo demais pra caber só numa delas, ele precisa atravessar as duas — e é empurrado até a fileira mais adiantada. O degrau que fica atrás dele é estreito demais pra qualquer palete e vira buraco. Carga solta no meio do baú anda na estrada.
✅ O conserto: o sistema monta o mesmo caminhão mais 4 vezes, mudando só a ORDEM em que os modelos entram, e fica com o arranjo que deixa menos buraco. Na sua carga do POWERDENT o vão de 43 cm some por completo, com os mesmos 15 paletes, e o baú ainda encurta de 5,28 m para 4,57 m.
🔒 A regra que ele nunca quebra: jamais leva menos palete e jamais deixa uma caixa ⭐ pra trás. Se nenhum dos 4 arranjos for melhor, fica exatamente o de hoje. A ordem de entrega também não muda — a 1ª entrega continua na porta e a última no fundo — e onde você ajustou a pilha na mão o sistema não encosta.
📏 Como ligar: Planejamento de Carga ▶ ⚙ Folgas ▶ ✓ Apertar o arranjo da carga. Nasce desligado de propósito: ele muda o DESENHO de mais ou menos 3 em cada 10 planos, e quem decide se quer isso é você — não o sistema, na virada da versão.
📊 Medido com dado seu: 500 cargas montadas com a geometria real das 174 caixas cadastradas — 0 levaram menos palete, 0 perderam ⭐, +71 paletes no total, 54 cargas ficaram sem buraco nenhum e 30 com buraco menor. Os 2 planos que você já tinha salvo (KININO e TCHETTO) saem idênticos: eles não tinham buraco de verdade.
⚠️ No caminho apareceu um defeito na própria conta: um "vão de 7,5 m" num plano real da KININO morava numa fatia de 2 cm de largura, entre o canto de dois paletes — buraco que palete nenhum ocuparia. Agora só conta como buraco o que tem largura de palete. Teste novo com 11 mutanções (tests/carga-arranjo-polimento.test.mjs).
✅ Não precisa do Luan: é só tela.
📦⬆️ O caminhão passou a aproveitar a altura que estava sobrando. Você olhou a vista 3D e disse: "esses 2 paletes cabem em cima do outro, assim ganho espaço no caminhão caso for carregar mais". Estava certo — e era defeito.
🔍 O que estava acontecendo: o sistema monta a carga em três etapas — primeiro as pilhas, depois tenta subir o que sobrou, e por último põe no chão o que restou. Só que depois dessa última etapa ninguém mais tentava subir: o palete que ia pro chão sozinho ficava com 1,8 m de altura livre por cima, e outro palete ficava DE FORA do caminhão mesmo cabendo ali.
✅ O conserto: tentar subir mais uma vez, depois do chão. Medido em 8.000 cargas diferentes: 18 passaram a levar mais palete (23 paletes a mais no total), nenhuma passou a levar menos e nenhuma gastou mais comprimento de baú.
⚠️ Na SUA carga do POWERDENT o desenho não muda — ali as alturas já fecham as colunas e o que sobra em cima (40 a 80 cm) não comporta palete nenhum. O ganho aparece quando os modelos têm alturas mais variadas. O modo sem empilhamento continua exatamente igual, e carga que já cabia inteira sai idêntica ao que era antes. Teste novo com 12 checagens, comparando o motor com e sem o conserto (tests/carga-altura-perdida.test.mjs).
✅ Não precisa do Luan: é só tela.
🔒 A trava que protege o histórico de romaneios finalmente entrou. Lembra dos 6 romaneios que sumiram em 21/08 — quando os números 1 a 6 foram reusados e a carga do KININO saiu com papel assinado "Nº 6" enquanto o sistema chamava de "Nº 5"? A causa foi um computador com versão antiga que gravou a lista inteira por cima da que estava no servidor. O sistema já tinha sido consertado pra gravar registro a registro, mas isso só protege quem está atualizado. Agora o próprio servidor recusa a gravação da lista inteira — e aí nem um aparelho com a versão velha em cache consegue apagar.
📋 Vale também para o resumo de "carregado parcialmente" (o que os apps leem pra mostrar quantos paletes já saíram), pelo mesmo motivo: é um mapa, e a proteção antiga só sabia contar lista.
Conferido antes de ligar: todas as telas de hoje já gravam do jeito certo, então ninguém vai receber erro por causa disto — quem receber é justamente a gravação que não deveria existir. Ficou com teste travando os dois lados, pra proteção não sumir de novo sem ninguém notar.
⚠️ Precisa do Luan: só pm2 restart all — não tem migration nesta.
↩ O palete que "ficou pra trás" agora VOLTA mesmo pro estoque — e todo mundo fica sabendo. Você marcou os paletes 1 e 11 da KININO CX 44 e eles não voltaram: 2.802 caixas reais sumidas da tela, sem um aviso sequer.
🔎 Por quê: aquele lote tinha saído inteiro do PA, e quando isso acontece a linha é apagada da tabela. O botão devolvia o palete no livro de saídas (isso funcionou), mas ninguém trazia a linha de volta — o sistema só sabia corrigir linhas que ainda existiam. Agora, quando há palete devolvido, a linha é recriada sozinha com o que sobrou, em qualquer computador.
🚚 E o pedido passa a mostrar "CARREGADO PARCIALMENTE", igual ao da VIVA GRAFICA: 9 de 11 paletes · 12.609 cx. Marcar "ficou pra trás" só faz sentido depois que o caminhão levou o resto — então esse clique passa a valer como prova do carregamento, mesmo quando a saída foi dada na mão. O selo aparece no PCP e em todos os apps.
📦 No app da Expedição, os paletes que ficaram aparecem em dois lugares: um aviso na tela inicial ("↩ Ficaram pra trás — bipe na próxima viagem deste cliente", com cliente, modelo e quais paletes) e marcados na conferência do PA na hora de carregar, pra ninguém confundir com lote novo.
⚠️ A linha só volta quando alguém marcou o palete como "ficou pra trás" — lote que saiu inteiro e está certo assim continua fora. ⚠️ Sem essa marca, baixa manual continua não valendo como carregamento (é a regra de 13/08, quando uma limpeza de PA marcou 7 pedidos como carregados sem caminhão nenhum). ⚠️ O aviso do app não conta palete que já saiu de novo. 24 checagens e 6 mutações de teste (tests/palete-ficou-pra-tras.test.mjs).
✅ Não precisa do Luan: é só tela. ⚠️ O tablet da Expedição precisa abrir o app uma vez pra pegar esta versão.
📦 O Planejamento de Carga parou de dizer "código sem caixa no cadastro" numa caixa que ESTÁ cadastrada. Aconteceu com a POWERDENT TIPO 02: o cadastro se chamava "CX TIPO 02", o palete no estoque foi etiquetado "TIPO 02 SEM IMPRESSAO" — e o sistema procurava a caixa pelo nome. Não achando, ele perdia a paletização (1.575 caixas por palete) e passava a chutar pelos 4 paletes do chão.
🔗 Agora ele procura pelo PEDIDO, não pelo nome. O palete sabe de qual pedido é, e o pedido guarda a caixa certa por dentro — o mesmo caminho que o romaneio passou a usar em 21/08, quando 3.000 kg ficaram fora do papel por esse mesmo motivo. O código do produto vem do Sectra e o do cadastro é escrito à mão: eles não precisam mais ser iguais.
📋 No Estoque PA, cada linha agora mostra a caixa ligada a ela — o nome do cadastro e quantas caixas cabem no palete — e tem um 🔗 pra ligar ou trocar essa caixa na mão, sem depender do nome. Quando não há caixa ligada, ele avisa em laranja em vez de ficar quieto.
⚠️ O vínculo é gravado no pedido (é de lá que o romaneio, a carga, o peso e a paletização tiram a caixa), fica registrado no histórico do pedido e respeita a permissão de editar. ⚠️ Caixa de outro cliente continua proibida — nem escolhendo na mão. ⚠️ Nas telas de carga o nome que aparece é o do cadastro, com o código do Sectra do lado, em cinza, pra ninguém perder o pedido de vista. Lote antigo sem pedido continua casando pelo nome, como sempre. 27 checagens e 6 mutações de teste (tests/caixa-do-palete-pelo-pedido.test.mjs).
✅ Não precisa do Luan: é só tela.
🔍 Dois arranhados na tela do Planejamento de Carga — achados abrindo o sistema no navegador de verdade.
📜 O aviso saía com código à mostra: ao tirar um palete na mão aparecia tirado na mão → <b>23 posições</b>. Os avisos do sistema são escritos como texto puro de propósito (assim nome de cliente com sinal esquisito nunca vira código), então a marcação aparecia crua. Agora sai limpo: "tirado na mão → 23 posições · 7,63 t de 8,00 t". Valia também pros dois avisos do ⚖️ Comparar.
✍️ E um erro de português meu: quando dois paletes cediam lugar pra outro entrar, o motivo saía "2 saiuram pra abrir espaço". Virou "2 saíram".
Nenhum teste de bancada pegaria esses dois — o primeiro só existe quando há um aviso de verdade na tela, e o segundo é texto. Por isso entrou junto uma checagem automática que recusa qualquer aviso do módulo escrito com marcação, pra não voltar. Nada mudou no funcionamento: os números, o encaixe e as contas são os mesmos.
✅ Não precisa do Luan: é só tela.
🎨 A nota de TINTA, COLA e FACA agora entra pelo XML. No Centro de Custo ▸ Lançamento de Insumos apareceu o botão "📄 Importar XML da nota": você escolhe o arquivo, o sistema abre a nota conferida — item por item, com o que cada um custou e quanto tem de crédito de ICMS e IPI — e você só diz qual produto do estoque é cada item. Depois é o "✅ Lançar" de sempre que grava: mesmo estoque, mesmo custo, nada de caminho novo.
💳 O crédito de imposto da compra para de se perder. Antes a compra de insumo era digitada à mão e o ICMS e o IPI da nota do fornecedor não ficavam registrados em lugar nenhum. Agora ficam, com NCM e CFOP, e o XML original é guardado junto.
🔒 O sistema NUNCA inventa o produto. Se um item da nota não casar com nada do seu estoque, ele entra no custo mas não mexe no saldo — e a tela avisa. Adivinhar produto por nome parecido já foi o erro mais caro deste sistema, e não vai voltar por aqui.
🐛 E um defeito foi pego e consertado no caminho: a leitura da nota de papel (que subiu hoje de manhã) estava misturando os impostos — numa nota de fornecedor do Simples, o código do IPI virava código de ICMS e a base do PIS virava base de ICMS. Ou seja, imposto aparecendo onde não existe. Agora a leitura é uma só, num arquivo só, e serve papel e insumo — duas cópias da mesma leitura sempre acabam diferentes, e essa foi a prova.
Nota já importada não entra duas vezes. Se o servidor ainda não estiver pronto, a tela avisa e não põe nada na lista — importar pela metade deixaria a compra lançada sem o crédito. Testado com nota fiscal de verdade: 120 checagens, todas verdes.
⚠️ Precisa do Luan: npm run db:migrate (migration 041) + pm2 restart all. Antes disso o botão avisa e nada quebra.
📥 A nota do fornecedor passa a ser guardada INTEIRA. Até agora, quando você importava o XML da nota de papel, o sistema anotava só o cabeçalho (fornecedor, número, valor) e os quilos por cliente — e jogava fora o resto. O resto é o que interessa: o NCM, o CFOP e principalmente os impostos destacados na compra, que são o seu crédito de ICMS e de IPI. Agora fica registrado, item por item.
📎 E o XML original fica guardado junto. É obrigação legal manter as notas (as recebidas também) por mais de 5 anos, e é a única forma de reprocessar uma nota se um dia a leitura melhorar.
🏢 Fornecedor do Simples é tratado diferente, como tem que ser: ele não destaca ICMS nem IPI, e o que ele transfere é só o crédito do Simples — gravado em campo próprio, sem misturar com o do fornecedor normal.
🔎 Pra que serve na prática: passa a dar pra responder "quanto entrou de cada NCM no mês" e "quanto tenho de crédito de imposto nas compras" — perguntas que não tinham de onde sair. É também a base do Bloco K.
A importação em si não mudou: se a leitura não achar um imposto no XML, ele fica zero — nunca um chute. Nota importada antes não ganha os itens de volta (o XML dela não tinha sido guardado); vale das próximas em diante.
⚠️ Precisa do Luan: npm run db:migrate (migration 040) + pm2 restart all. Sem isso a importação continua funcionando exatamente como antes, só sem guardar os itens.
🧱📱 A carga batida chegou no app do expedidor — e a bipagem é a de sempre. Agora dá pra liberar pro carregamento um plano com 🧱: o expedidor bipa o QR dos paletes normalmente, o placar conta certo e a baixa no Estoque PA acontece — exatamente como você pediu ("conferi com os paletes, porém ele vai sem os paletes na hora de colocar no caminhão").
🔑 O que estava errado: o app casa cada bipagem com os paletes desenhados no plano, e o cliente batido não tem palete no desenho (no baú ele é parede de pacotes). Resultado: o expedidor bipava e levava "❌ Fora do plano" — o palete não entrava na carga e não saía do PA. Na v2.37.520 eu tinha só impedido de liberar esse plano; agora o problema foi resolvido de verdade: o plano manda a lista dos paletes batidos e a doca trata igual aos outros.
🔬 Na hora de bipar o app avisa: "🧱 BATIDA — tire as caixas do palete e ponha soltas no baú (o estrado fica)". Quem é paletizado não vê nada diferente.
🚚 Caminhão inteiro de um cliente só em batida agora monta — antes o sistema respondia "monte um plano válido" com o plano montado na frente, porque ele exigia palete desenhado e ali só existe parede. É justamente o caso mais comum de batida.
🗺️ O painel "Expedição ao vivo" do escritório passou a contar os paletes batidos: ele dizia 8 onde o app dizia 26 no mesmo caminhão.
A trava do "fora do plano" continua igual de rigorosa pra quem realmente não está na carga, e palete repetido segue sendo recusado. Cliente com um modelo batido e outro paletizado recebe o aviso só no palete certo. Plano sem batida (todos os de hoje) não ganha campo nenhum e o app se comporta exatamente como antes. Teste novo exercitando as funções reais do app (não por regex): 53 checagens e 8 mutações, todas acusadas (tests/carga-batida-no-app.test.mjs).
✅ Não precisa do Luan: é só tela.
🏢 Agora você escolhe no ORÇAMENTO por qual empresa a nota vai sair. Apareceu o campo "🏢 Faturar por" na caixa de totais: a JP (Lucro Presumido) ou a segunda empresa (Simples Nacional). A escolha viaja sozinha — vai junto pro pedido, aparece na fila da 💵 Baixa com o selo 🏢, e a pré-nota já nasce daquela empresa (dá pra trocar na hora, se precisar). Enquanto só existir uma empresa cadastrada, o campo nem aparece e tudo continua exatamente como era.
💰 A escolha muda o preço, e o sistema explica por quê. Pelo Simples não existe IPI por fora (o campo zera e trava sozinho) e os impostos que entram no preço deixam de ser ICMS+PIS+COFINS pra ser a alíquota do DAS. Enquanto o contador não passar essa alíquota, o preço continua sendo calculado pelo Presumido — ou seja, mais ALTO — e a tela avisa que falta o número. Preferi errar pro lado caro: preço alto a gente negocia, preço baixo já saiu.
⚖️ E um aviso honesto na hora de escolher: faturando pela empresa do Simples, o seu cliente não credita ICMS nem IPI — credita só uma fração (o crédito do Simples). Pra cliente que é indústria isso muda o custo real dele, então a tela mostra o número na sua frente em vez de deixar a escolha parecer que dá no mesmo. O papel do orçamento também passou a dizer quem vai faturar, no sistema e no app do vendedor.
🧾 A nota da empresa do Simples é outro papel (e já sai certo): sem ICMS e sem IPI destacados — eles vão dentro do DAS —, com o CSOSN no lugar do CST, sem o IBS/CBS da reforma (o Simples só informa a partir de 2027) e com os textos que a lei obriga. O crédito que o cliente pode aproveitar sai em destaque. Sem a alíquota do contador, ela não inventa crédito: avisa.
📄 O espelho da pré-nota agora tem o desenho da nota fiscal de verdade — canhoto, emitente, destinatário, fatura, cálculo do imposto, transportador, itens, dados adicionais, na mesma ordem do DANFE que você já conhece. Mas sem código de barras, sem chave de acesso e sem protocolo: é isso que impede alguém de confundir com nota fiscal. A tarja vermelha SEM VALOR FISCAL continua atravessada.
🐛 E o IPI da caixa estava errado no sistema. Conferindo a sua NF-e nº 25.718 conta por conta, o IPI real é 15% — o sistema estava com 0% e avisando 9,75%. Naquela nota a pré-nota sairia R$ 4.568,84 mais barata que a real. Corrigido: agora o sistema reproduz aquela nota centavo a centavo, item por item.
Testes: a suíte inteira verde (105 checagens). As telas novas têm teste próprio com mutação conferida — inclusive a que garante que a falta do número do contador nunca deixe o preço sair barato.
⚠️ Precisa do Luan: npm run db:migrate (migrations 037, 038 e 039) + pm2 restart all. Antes disso o botão avisa e nada quebra.
⚠️ Precisa de você: os dados do 2º CNPJ (hoje estão como CONFERIR_) e, com o contador, a alíquota do DAS e a faixa do Simples. E a janela do "Simples híbrido" fecha em 30/09/2026.
🧱 CARGA BATIDA — as caixas sobem SOLTAS no caminhão, e o estrado fica na fábrica. No Planejamento de Carga, cada cliente ganhou o botão 🧱 batida (ao lado do 🔒): as caixas dele deixam de ir paletizadas e viram paredes de pacotes — os mesmos pacotes do cadastro, empilhados na seção do baú (testando as 2 orientações), fileira atrás de fileira. Ocupa menos caminhão: os 540 pacotes do caso de teste fazem 4,7 m de baú onde paletizado seriam ~5,4 m.
👍 A conferência NÃO muda nada (como você decidiu): o expedidor bipa o QR dos paletes como sempre — na hora de pôr no baú é que as caixas sobem soltas e os estrados ficam. O plano, o WhatsApp e o PDF avisam isso com todas as letras.
⚖️ O peso desconta os estrados (eles não viajam): "🧱 batida sem estrados: −450 kg" na régua. E o peso do estrado agora é configurável na engrenagem ⚙️ junto das folgas (padrão 25 kg).
📦 Tudo que já existia continua valendo pra batida: os chips são os mesmos lotes bipáveis (📌 tirar na mão funciona igual), quem não cabe desce pro FICA PRA TRÁS e pra Fila de Re-embarque, e o motor de empacotar (intacto) monta os paletizados no comprimento que sobra.
Na planta a batida aparece como bloco com um risquinho por fileira; na 3D, parede até o teto sem o estrado de madeira. Modelo sem os dados do pacote no cadastro (caixa dobrada, altura do pacote, peças por amarrado) continua indo paletizado, com aviso — batida não se inventa. Plano sem nenhum cliente 🧱 serializa idêntico ao de antes. 38 checagens e 6 mutações de teste (tests/carga-batida.test.mjs).
✅ Não precisa do Luan: é só tela. Com esta, as 7 fases do Planejamento de Carga v2 estão completas.
💬 O vendedor agora pede REVISÃO DE PREÇO por caixa, direto na tela do aceite. Na hora de marcar o que o cliente fechou, cada caixa ganhou o botão "💬 Revisar preço": dá pra dizer o preço que o cliente aceita e o motivo. As caixas ✓ seguem virando pedido sozinhas; a caixa em revisão vai pro PCP rever — e pedir revisão não é aceitar: dá até pra mandar só a revisão, sem fechar caixa nenhuma.
🖥️ No PCP o cartão do orçamento mostra o pedido em destaque ("CX 22: R$ 1,97/cx → o cliente quer R$ 1,80 · concorrente cobriu") com o atalho "✓ Preço revisado — liberar de novo" — é o mesmo Aprovar preço de sempre. Você edita o preço no ✏️ Editar, libera, e o app do vendedor reabre o aceite sozinho com o preço novo: ele aceita a caixa e ela vira pedido na hora. O ciclo inteiro fecha sem telefone.
Caixa que já virou pedido ou que foi recusada aparece travada na tela do aceite (não tem como mexer de novo). O mesmo aceite antigo nunca é reaplicado depois da re-liberação — senão a janela do vendedor fechava sozinha. No modo administrador, a revisão sai carimbada "✍️ pelo adm". Teste novo: 27 checagens do ciclo inteiro + 5 sabotagens, todas acusadas (tests/revisao-preco-vendedor.test.mjs).
✅ Não precisa do Luan: é só tela.
🧾 Nasceu o FATURAMENTO — por enquanto em modo de ENSAIO, sem valor fiscal. Na tela Expedição → 💵 Baixa (a fila de quem carregou e está liberado pra faturar), cada pedido ganhou o botão 🧾 Pré-nota: ele monta a nota fiscal COMPLETA como ela sairia de verdade — NCM, CFOP, CST, ICMS (18% em SP, 12%/7% pra fora), IPI, PIS/COFINS e o IBS/CBS da Reforma Tributária, que é obrigatório na nota desde 03/08/2026 — e imprime um espelho com a tarja vermelha SEM VALOR FISCAL (de propósito ele NÃO parece um DANFE: sem código de barras, sem chave). Nada vai pra SEFAZ: a nota oficial continua saindo no Sectra até a fase do certificado digital.
🔢 A pré-nota tem numeração própria de TESTE e fica guardada no banco pra sempre — cancelar não apaga, marca como cancelada com motivo e registro (a regra da casa). A quantidade vem do romaneio (o que embarcou de verdade), o preço vem do pedido, e o CNPJ/IE/UF vêm do cadastro do cliente — o que faltar lá, a tela avisa e deixa completar na mão.
📦 O cadastro da caixa ganhou o bloco "🧾 Fiscal" (item 11 do modal): NCM, unidade, origem, CST do ICMS, alíquota de IPI, CST IBS/CBS e cClassTrib. Caixa que ainda não tem cadastro próprio abre dizendo "está usando o perfil padrão de papelão ondulado" em vez de fingir que tem — e só ganha o dela se você mexer em algum campo. Se o IPI ficar em 0%, a tela avisa que a TIPI aponta 9,75% pra caixa de papelão e pede pra confirmar com o contador (a gente não chuta imposto).
🔎 Na fila da Baixa, quem já foi ensaiado mostra o número — "🧾 Pré-nota Nº 3 · TESTE" — em vez de você ter que procurar lá embaixo na lista.
🐛 Um defeito sério foi pego antes de chegar na fábrica: a pré-nota de qualquer pedido com a caixa amarrada ia dar erro e não sair — o sistema procurava a caixa por um código que não cabia na ficha do banco. Consertado e provado num banco de verdade. Junto com ele, outro: o cadastro fiscal guarda histórico, e a tela podia abrir mostrando uma versão antiga do NCM/IPI em vez da última — agora é sempre a mais recente.
💵 Nada mudou na baixa: continua sendo ela que tira o pedido da carteira e gera as parcelas no Contas & Previsão (com a condição de pagamento do cliente, que já alimenta a Previsão de caixa). A pré-nota só pergunta no final se você já quer dar a baixa também — um gesto puxa o outro, nenhum duplica o outro.
A conta dos impostos é a do módulo fiscal que já morava no banco (migration 023), conferida centavo por centavo contra uma NF-e real autorizada — inclusive a regra do centavo que a SEFAZ valida (soma dos itens = total da nota). A pesquisa completa de como emitir de verdade (certificado A1, provedores tipo Focus NFe, reforma tributária 2026→2033, Bloco K, boleto) está no PLANO_FATURAMENTO_v1.md, com as 4 decisões que você tomou. Testado: validação pura, o fluxo inteiro num PostgreSQL de verdade (numeração contínua, totais, cancelamento que não apaga) e as duas telas novas exercitadas no navegador — tests/pre-nota-teste.test.mjs e tests/fiscal-caixa-e-selo.test.mjs, este com 4 mutações, todas acusadas.
⚠️ Precisa do Luan: npm run db:migrate (migrations 037, 038 e 039) + pm2 restart all. Enquanto isso não rodar, o botão avisa educadamente e nada quebra.
📦 CAIXA MONTADA (coletiva) — a conta que o CLIENTE faz, agora dentro do cadastro. Na seção de Paletização da caixa apareceu o modo 📦 Caixa MONTADA: você informa o C×L×A externo da caixa fechada e quantas unidades de produto cabem nela (ex.: 10 pacotes de farinha) — e o sistema responde o lastro, as camadas, caixas por palete, unidades por palete, a % da área do lastro e do cubo útil e a altura final do palete montado.
🚚 E simula direto num caminhão do cadastro: "MB 1620: 14 posições × 2 níveis = 28 paletes → 1.680 caixas → 16.800 unidades de produto" — testando as duas orientações do palete no baú, como o empacotador do plano faz.
⚖️ O motor é o MESMO da paletização de sempre (amarração > colunar, overhang, regra do caminhão) — só trocou a peça: a caixa montada no lugar do pacote dobrado. No caso de teste do documento ele fez melhor que a conta simples: a amarração fecha 10 caixas por camada (100% do chão do palete) onde o colunar fazia 9.
📋 No Planejamento de Carga e no Resumo do WhatsApp, cliente cuja caixa tem o modo ganha a linha: "📦 montadas, viram 135.000 unidades de produto" — a contagem por unidade que o cliente usa pra conferir o abastecimento dele.
Fica salvo dentro da paletização da caixa (sem migration, sem Luan); nada do modo dobrado muda, e caixa sem o campo segue exatamente como era. A conta mora num lugar só (js/19) — o cadastro, o plano e o resumo só leem. 5 mutações de teste (tests/carga-caixa-montada.test.mjs), inclusive "esquecer o estrado na altura útil" e "o salvar da caixa engolir a montada".
✅ Não precisa do Luan: é só tela.
🔗➡️📋 O aceite do CLIENTE pelo link também vira pedido sozinho. Quando o cliente aprova o orçamento pelo link (a caixa que marcar, ou tudo), os pedidos nascem na hora no Cronograma — a mesma regra que o aceite do vendedor ganhou na v2.37.515, agora nas duas portas de fora.
O aceite do link ainda vem conferido pelo próprio servidor: se alguma caixa não bater com o orçamento (o PCP reeditou depois de mandar o link), NADA vira pedido no escuro — fica pro botão de sempre, com o aviso no cartão. O aceite registrado pelo PCP na central continua manual, e aceites antigos que já estavam esperando não geram nada na virada. Mesmos ids fixos contra pedido em dobro entre dois PCs. Teste ampliado: 27 checagens e 5 sabotagens, todas acusadas.
✅ Não precisa do Luan: é só tela.
🤝➡️📋 O aceite do vendedor agora VIRA PEDIDO SOZINHO. Quando o vendedor registra pelo app que o cliente fechou — a caixa que ele marcar, ou o orçamento inteiro — os pedidos nascem na hora no Cronograma, já programados, sem ninguém do PCP precisar clicar "Gerar caixas + pedidos". A caixa que ele não marcou fica EM ABERTO como antes (não vira pedido sem gente) e o botão continua no cartão pro resto.
📅 A data da 1ª entrega sai da régua de sempre: prazo do cliente, senão o padrão da casa. O acabamento vem do cadastro da caixa. É a MESMA geração do botão — mesmos carimbos, mesmas travas — só que automática.
Dois PCs com o sistema aberto processando o mesmo aceite geravam risco de pedido EM DOBRO — por isso o pedido automático nasce com id fixo (orçamento+caixa+entrega): se dois PCs correrem, o servidor funde no mesmo pedido. O aceite do cliente pelo link e o do PCP continuam manuais (foi o combinado). Aceites antigos que já estavam esperando NÃO geram nada sozinhos na virada. Teste novo com 23 checagens e 5 sabotagens, todas acusadas (tests/aceite-vira-pedido.test.mjs).
✅ Não precisa do Luan: é só tela.
📤 RESUMO DA VIAGEM PRONTO PRO WHATSAPP. No Planejamento de Carga, o botão 📤 Resumo monta o texto da viagem inteirinho: por cliente, o que VAI (com a composição dos paletes no mesmo formato do romaneio — "18 × 750" — pro cliente comparar os dois papéis) e o que FICA, com o motivo, a % do pedido e a entrega (🔴 quando já está atrasando). Botão 📋 Copiar e 📤 Compartilhar (no celular).
⚖️ Os números são OS DA TELA — o texto lê o mesmo plano da régua: o "≥" de caixa sem peso viaja junto, e peso estourado sai escrito com quantos kg passou ("avisa, não trava"). Com o estudo A/B aberto, o resumo sai com a tarja ESTUDO — NÃO VALE NA DOCA.
🖨️ O PDF do plano também cresceu: a seção "Ficou pra trás" (que era só cliente + quantidade) virou "⛔ Fica pra trás" completa — motivo de cada linha, % do pedido, caixas, peso e a entrega marcada quando atrasa. A mesma fonte do painel da tela, então papel e tela nunca divergem.
Plano antigo (sem os campos novos) imprime como antes. 6 mutações de teste (tests/carga-resumo-viagem.test.mjs) — inclusive "o resumo inventar conta própria de peso" e "a composição virar uma 2ª cópia".
✅ Não precisa do Luan: é só tela.
⚖️ COMPARAR CENÁRIOS A/B — "e se eu montasse diferente?", sem medo de perder nada. No Planejamento de Carga, o botão ⚖️ Comparar (ao lado do Remontar) congela o jeito que está como Cenário A. Daí é mexer à vontade nos chips — a tela vira o B, e os dois ficam lado a lado: mini-planta, posições, peso (com o "≥" de sempre), cubagem, entregas completas e o bloco vermelho de quem fica em cada um, com um veredito de uma linha embaixo ("A deixa 5.960 cx · B deixa 2.700 cx — peso A 7,89 t × B 8,40 t").
💭 Estudo é só estudo: a tarja roxa "ESTUDO — não vale na doca" fica em cima (e sai no PDF, se imprimir com a comparação aberta). Nada vai pro servidor até decidir — fechar a comparação descarta tudo.
⭐ Aplicar decide e deixa ESCRITO: o escolhido vira o plano, e o estudo inteiro fica gravado dentro dele — os dois cenários, quem escolheu e quando, com o preterido marcado "descartado" (nada se apaga; decidir de novo guarda a decisão anterior também). Dá pra ver no 👁 Ver do histórico.
⛔ Plano que a doca já começou a carregar não aceita Aplicar — as bipagens do expedidor casam com as pilhas salvas, e trocar o desenho embaixo delas seria estrago. Comparar pode; aplicar, só num plano novo.
O cenário A restaurado devolve TUDO que estava congelado: os 📌 tirados na mão, os 🔒 de carga fechada, as ⭐, a ordem e até o caminhão escolhido. Plano antigo sem decisão abre igual ao de sempre. 7 mutações de teste (tests/carga-cenarios-ab.test.mjs).
✅ Não precisa do Luan: é só tela.
📦 FILA DE RE-EMBARQUE — o que ficou pra trás virou a próxima carga, não uma lembrança. No Planejamento de Carga, logo abaixo do histórico, uma seção nova junta tudo que ficou de todas as viagens: o que o plano cortou (com o motivo de cada linha) e o que a doca não bipou (com o motivo que o expedidor já escolhe no fecho — "palete avariado", "não coube"…).
✅ Palete que sai por QUALQUER porta some da pendência sozinho — mas nunca calado. A fila confere cada linha com o que ainda existe no estoque PA: saiu por outro plano, por carga da escala, avulsa ou baixa manual, a linha vira cinza "✔ resolvido — saiu por carga avulsa 21/08", com a explicação lida do livro de saídas. Ninguém precisa limpar fila.
▶ "Montar a próxima viagem com isso": um toque abre um plano rascunho normal, com os clientes na ordem de entrega e cada modelo pendente já com ⭐ (tem que ir). Nada é baixado nem reservado — o plano recalcula com a geometria do cadastro e o que existe no PA de verdade, como sempre; a fila só aponta.
📱 No app da Expedição, a tela de "caminhão carregado" ganhou uma linha: os paletes que ficaram já estão na fila da próxima viagem.
🛠 De quebra, um buraco fechado: o re-salvar de um plano pelo PCP apagava o motivo que a doca tinha gravado (a barreira preservava as bipagens mas não o faltaMotivo/faltaPaletes) — agora preserva os dois.
A fila é derivada e 100% leitura (como o selo "carregado parcialmente"): nada novo pra sincronizar, nenhum escritor novo no servidor. A conta mora num arquivo só (js/63-reembarque.js), que não alcança nada de ninguém — cada tela entrega os seus dados. O elo é o pedidoId (código+cliente só de reserva, nunca de outro cliente), e o mesmo pedido deixado em duas viagens seguidas não vira o dobro: a menção mais recente manda. 8 mutações de teste (tests/carga-reembarque.test.mjs).
✅ Não precisa do Luan: é só tela.
👆 Decidir a carga virou tocar no palete. No Planejamento de Carga, cada palete previsto agora é um chip na cor do cliente: P7 · 750 cx, com ½ no parcial e 🏭 no que ainda está em produção. Tocar tira do caminhão; tocar de novo devolve. O que você mexeu ganha 📌 e o automático não desfaz — nem o Remontar, nem o resgate de prioridade.
🔄 Devolver com o caminhão cheio faz troca explicada: sai o último palete sem 📌/★ do cliente de entrega mais tardia, e o aviso diz quem entrou, quem saiu e quanto ficou o peso. Se não dá (tudo é prioridade), ele recusa e desfaz a tentativa inteira — nunca fica meia troca.
★ No chip dá pra marcar "tem que ir" (vale pro modelo inteiro, a mesma ⭐ da lista de cima) e 🔒 carga fechada por cliente: ninguém corta dele.
📋 O painel ⛔ FICA PRA TRÁS agora diz as três origens de cada corte: "tirado na mão 📌", "saiu pra abrir espaço (troca)" ou "cortado: entrega mais tardia (automático)" — e os chips de quem ficou aparecem na faixa, prontos pra devolver com um toque. O aviso azul antigo encolheu pra uma linha (o detalhe mora no painel).
O motor de empacotar não foi reescrito: o que você tira na mão vira um TETO que entra ANTES do empacotamento — é isso que faz o lugar sobrar de verdade pros outros. Detalhe físico honesto: a vaga no chão é uma pilha (2 paletes de 1,2 m num baú de 2,7 m); tirar UM deixa meia pilha que outro modelo não reaproveita — tirar o segundo libera a vaga inteira. O plano salvo guarda os 📌 e os 🔒 (plano antigo abre igual, sem eles). 9 mutações de teste (tests/carga-chips-vai-fica.test.mjs).
✅ Não precisa do Luan: é só tela.
⚖️ O Planejamento de Carga passou a pesar o caminhão. Até agora ele só sabia dizer quantos paletes cabem e quantos metros de baú isso ocupa. Só que caminhão fecha no peso muito antes de fechar no espaço — e ninguém via isso na tela. Agora tem o card Peso da carga, com a capacidade do cadastro do caminhão: 7,89 t de 8,0, com barrinha.
⚠ Estourou o peso, a régua fica vermelha e diz quanto passou — e o plano continua salvando do mesmo jeito. Peso avisa, nunca trava: quem decide se vale a pena é você, não o sistema.
⚖️ E quando ainda sobra espaço mas já não sobra quilo, aparece o selo "peso fecha primeiro" — que explica por que a carga parou com o baú pela metade.
≥ Caixa sem peso cadastrado não vira chute. O total passa a sair como "≥ 6,2 t" com o aviso "3 paletes sem peso no cadastro" e um atalho pra preencher. Somar zero calado faria o total parecer certo justamente onde ele não está.
⛔ Quem fica pra trás ganhou painel próprio. Antes era uma linha de aviso. Agora, por cliente: quantos paletes ficam, quantas caixas, quanto do que ele tinha isso representa, a data de entrega dele (com 🔴 quando já está atrasando) e o motivo de cada linha — "cortado: entrega mais tardia" ou "não coube nem com prioridade".
O peso sai da mesma conta do romaneio (caixa do pedido → peso da caixa × quantidade), mais 25 kg do estrado de madeira por palete — duas contas diferentes fariam o papel que vai com o caminhão discordar da régua que decide o embarque. O painel conta pela mesma fonte do número da régua, pelo mesmo motivo. Nada foi baixado do estoque: o que fica continua no PA, disponível pra próxima viagem. O motor de empacotar não foi tocado — isto é uma camada de decisão por cima dele. Plano antigo abre igual, e o plano salvo passou a guardar o peso e o porquê de cada corte. 8 mutações de teste (tests/carga-regua-peso.test.mjs), com o cenário de aceite batendo certinho: 24 posições, 7.890 kg, 8 paletes e 5.960 cx pra trás.
✅ Não precisa do Luan: é só tela.
🔑 O administrador agora consegue entrar no app do vendedor — sem a senha de ninguém. Na tela de login do app apareceu o botão discreto "Acesso do administrador": você entra com o seu e-mail e senha do sistema (a senha da Tatiane continua só dela), escolhe qual vendedor quer ver, e o app abre exatamente como aquele vendedor vê — clientes, orçamentos, pedidos, comissão. Serve pra conferir se está tudo aparecendo certo pra eles.
👁 Uma faixa amarela fica fixa na tela o tempo todo — "MODO ADMINISTRADOR — você está vendo o app como Tatiane" — com o botão 🔁 Trocar de vendedor, que pula de um pra outro sem digitar senha de novo.
✍️ Tudo que você alterar por ali fica registrado como feito por você, nunca como se fosse o vendedor: solicitação de orçamento, recompra e aceite saem carimbados, e o PCP vê o carimbo amarelo "✍️ pelo adm" no cartão. Excluir é bloqueado no modo administrador — exclusão não deixa rastro, e o combinado é que toda alteração fique registrada. Só o perfil admin passa; qualquer outra combinação recebe a mesma resposta de senha errada (a tela de login não pode entregar quem é admin).
O crachá que nasce no servidor fica gravado como mestre:<seu email> — no banco também fica escrito que quem entrou foi o adm. Teste novo com 6 mutações, todas acusadas (tests/acesso-mestre-vendedor.test.mjs), inclusive "deixar não-admin entrar" e "resposta que entrega quem é admin".
⚠️ Precisa do Luan: pm2 restart all (rota nova na API; não tem migration). Até o restart, o botão avisa que o recurso ainda não está instalado — o login normal dos vendedores segue funcionando igual.
😌 O ritmo do sensor parou de ficar inquieto na tela. Mesmo já alisado, o número ficava mexendo sozinho — 1.918, depois 1.937, depois 1.925. Agora ele anda de 50 em 50 acima de mil (1.900 → 1.950 → 2.000). Ninguém decide nada com 19 caixas/h de diferença, e mostrar essa casa só fazia o número parecer nervoso.
⏱️ E a média ficou mais lenta: o valor novo entra com 20% de peso (era 30%), então ele leva uns 25 s pra acompanhar uma mudança real de ritmo.
Abaixo de mil ele vai de 10 em 10, e abaixo de cem fica exato — numa máquina devagar cada caixa conta. Arredondar não custa atraso nenhum, ao contrário de alisar mais: foi o jeito mais barato de acalmar a tela. A regra mora num lugar só, lida pelo Mural e pelo app do operador — duas telas arredondando diferente mostrariam números diferentes do mesmo sensor. 42 checagens no teste do operador.
🤏 O app da Expedição também se mexe com os dedos. No botão 🔍, ao lado de "Planta / 3D", o desenho da carga abre em tela cheia: pince pra dar zoom, arraste com o dedo e dois toques pra aproximar. Numa carga cheia, o quadradinho de cada palete era pequeno demais pra conferir no tablet.
📸 A foto do caminhão também. As miniaturas antes da carga fechar têm 88 pixels — não dava pra conferir se a placa ficou legível antes de enviar. Agora é só tocar na foto.
🔄 Bipando com a tela aberta, o desenho acompanha — e sem perder o zoom: quem estava olhando um canto do baú continua nele, com o palete novo já pintado.
O girar o 3D com o dedo na tela normal continua igual (não foi tocado): a tela de perto mostra a pose atual, parada, pra examinar. A tela de "ver de perto" passou a morar num arquivo só (js/62-zoom-dedo.js), a MESMA do app da Qualidade — duas cópias de uma tela sempre acabam diferentes uma da outra. Medido no navegador de verdade: o ponto embaixo do dedo sai 0,0 px do lugar, a planta cabe inteira ao abrir e o zoom se mantém quando o desenho muda. 8 mutações de teste (tests/zoom-dedo-telas.test.mjs).
✅ Não precisa do Luan: é só tela.
🚚 O selo "CARREGADO PARCIALMENTE" agora aparece em TODOS os apps que mostram pedido — motorista, Qualidade, operador, encarregado, escala, vendedor e onduladeira (a Expedição e o PCP já tinham). Sempre o mesmo texto e o mesmo número: 1 de 3 paletes · 1.051 cx.
🚛 No app do motorista ele aparece embaixo de cada pedido da carga (nas de hoje e nas entregues): dá pra ver na hora que aquele cliente vai receber só uma parte, e que o resto ficou na fábrica.
🔗 E ficou pronto o caminho pra interligar tudo num site no futuro. Os apps não têm (nem devem ter) o livro de saídas de palete nem o Estoque PA — colocar isso no celular do motorista seria baixar o estoque inteiro pra mostrar uma linha. Então o sistema passou a publicar um resumo pequeno por pedido (quanto do pedido já embarcou), e qualquer tela lê esse resumo com uma linha de código. Um site futuro entra pela mesma porta, sem tocar no banco.
⚠️ Resumo que não chegou = tela como era. Nenhum app inventa número: sem o resumo, o selo simplesmente não aparece. ⚠️ O sistema não publica com o Estoque PA vazio (foto incompleta apagaria o selo da fábrica inteira) e não apaga pedido do resumo: quando o pedido leva tudo, ele é republicado como "fechado" e o selo some sozinho em todas as telas. ⚠️ Publicação por merge (vários PCs rodam o sistema) e só quando algo muda. A régua continua uma só: palete que saiu em carga bipada; baixa manual do PA não é carregamento. 63 checagens e 13 mutações de teste (tests/carregado-parcialmente.test.mjs).
✅ Não precisa do Luan: é só tela. ⚠️ Cada aparelho (tablets e celulares) precisa abrir o app uma vez pra pegar esta versão.
🌊 O número do sensor parou de andar aos trancos. O ESP32 manda os dados de 5 em 5 segundos, então a contagem chegava em lote: o número ficava parado e dava um salto de 10 de uma vez. Agora ele caminha até o valor real, num passo curtinho. Medido: um salto de 100 caixas se completa em 3,2 s — antes do próximo lote, então ele chega no número exato e descansa lá.
📉 E o ritmo ficou mais calmo ainda. A média passou a olhar 1 minuto (era meio) e ganhou uma segunda camada que faz o número deslizar em vez de dar passos: o valor novo entra com 30% de peso e o que está na tela fica com 70%.
Três travas: o número nunca mostra mais que o real (é o que o operador confere contra a contagem dele); pedido novo entra direto, sem deslizar pra baixo — isso pareceria produção sumindo; e se o ESP32 reiniciar, a média antiga é jogada fora junto com o histórico, senão a primeira leitura sairia arrastada por um ritmo que não existe mais. ⚠️ O atraso de 5 s do aparelho continua — não dá pra mostrar dado que ainda não chegou; o que mudou é que a tela preenche o intervalo em vez de ficar congelada. 82 checagens nos 4 testes do sensor.
🤏 O app da Qualidade também se mexe com os dedos. Tocando na folha do laudo ou em qualquer foto do teste, ela abre em tela cheia: pince pra dar zoom, arraste com o dedo e dois toques pra aproximar (outros dois voltam pra folha inteira). Tem também os botões − FIT + e a % do zoom, pra quem está no computador.
🖼️ A foto do teste parava de sair do app. Antes ela abria numa aba nova do navegador — o laudista saía do app pra ver a própria foto que acabou de tirar, e voltava no braço. Agora abre ali mesmo, encaixada inteira na tela.
📄 A folha que você amplia é a MESMA que vai sair no papel — na largura da folha A4, sem requebrar o texto. É uma cópia: a prévia da tela não é tocada, então o PDF, o WhatsApp e a impressão continuam exatamente como estavam.
A impressão do laudo já saía numa folha A4 só (desde a v2.37.377) e não foi mexida. O gesto mora num arquivo só (js/62-zoom-dedo.js), pronto pra outras telas do sistema — em aparelho antigo, sem suporte, nada muda e a dica "pince" nem aparece. Medido no navegador de verdade: o ponto embaixo do dedo sai 0,0 px do lugar, inclusive quando a folha cresce e passa a rolar. 8 mutações de teste (tests/zoom-dedo-qualidade.test.mjs).
✅ Não precisa do Luan: é só tela.
🚚 O selo "CARREGADO PARCIALMENTE" agora aparece TAMBÉM no app da Expedição — o mesmo que nasceu na Carteira do PCP na v2.37.499, com o mesmo texto e o mesmo número.
📍 Em três telas do app: no 📦 Estoque PA (o grupo do cliente/modelo avisa que aquele pedido já foi em parte e o que está ali é o resto), na conferência dentro da carga (do lado do "5 de 10 nesta carga", dizendo o que já saiu em cargas anteriores) e no histórico de cargas (marcando o pedido daquela carga que ainda tem palete no PA).
⚠️ A conta e o desenho agora moram num arquivo só (js/62-carregado-parcial.js), usado pelo sistema e pelo app: duas cópias divergiriam sozinhas e o expedidor leria um número, o PCP outro. As regras continuam as mesmas — só conta palete que saiu em carga bipada (baixa manual do PA não é carregamento), some quando o pedido leva tudo, e nada é gravado no pedido. ⚠️ O app conta em cima do lote inteiro, não do que sobrou no estoque, e quando não dá pra saber o tamanho do lote ele não chuta: prefere não mostrar selo nenhum. 39 checagens e 8 mutações de teste (tests/carregado-parcialmente.test.mjs).
✅ Não precisa do Luan: é só tela. ⚠️ Os tablets da Expedição precisam abrir o app uma vez pra pegar esta versão.
📉 O ritmo do sensor parou de dar saltos absurdos. O cartão chegou a mostrar 22.200 cx/h numa máquina cuja meta é 3.000. O motivo: o sensor conta em rajada — dispara 30 peças num segundo, para dois, espera, dispara de novo — e o número que o aparelho mandava era o da rajada, não o da máquina.
🔢 Agora o sistema mede por conta própria: guarda as leituras, vê quanto o contador subiu e divide pelo tempo que levou. A rajada e a espera entram na mesma conta e se anulam. A janela é de 30 segundos e já começa a falar com 10 — um minuto deixaria o número lerdo, mostrando ritmo depois de a máquina já ter parado.
⚡ E o app do operador ganhou o ritmo ao vivo, em número grande, embaixo da sugestão do sensor: verde acima de 85% da meta, amarelo abaixo — a mesma régua do Mural, pra as duas telas não discordarem sobre o que é "no ritmo".
Enquanto a conta não fecha os primeiros segundos, a tela diz "medindo…" em vez de mostrar o número cru. Aparelho mudo não mostra ritmo nenhum (seria o de meia hora atrás), e máquina realmente parada mostra zero — que é resposta, não "não sei". ⚠️ Isso deixa o número legível, mas não conserta o sensor: a rajada existe porque o aparelho está enxergando errado. 51 checagens novas e 5 mutações de teste.
©️ A assinatura de autoria da MTX Desenvolvimento entrou no sistema. Uma linha discreta: Copyright © 2026-2026 MTX DESENVOLVIMENTO All rights reserved.
🖥️ No pé de todas as 21 telas — o sistema, os 18 aplicativos (operador, qualidade, expedição, manutenção, compras, almoxarifados, motorista, vendedor, escala, onduladeira, bobinas, desenvolvimento, encarregado, ponto, RH, DRE, conciliação) e as duas páginas que o cliente abre (portal da arte e aprovação de orçamento).
🧾 E nos papéis: no romaneio que vai com o caminhão (embaixo do canhoto de recebimento), na nota do orçamento que vai pro cliente (no rodapé, depois das condições), no laudo técnico (embaixo das assinaturas do laudista e da Qualidade) e na etiqueta de palete (uma linha fininha no pé da folha, embaixo de Operador/Cliente/Data). Em todas as saídas de cada um: a impressão pelo sistema e o PDF do celular.
🏷️ A etiqueta não mudou de desenho. A linha entrou no espaço que já sobrava embaixo do rodapé — continua uma folha por palete, o QR ficou no mesmo lugar e nada foi empurrado. O laudo continua cabendo numa folha A4 só (conferido gerando o PDF de verdade).
✍️ O texto mora num arquivo só. Se um dia mudar o nome, o ano ou a forma de escrever, muda em um lugar e vale em todas de uma vez — não tem como uma tela ou um papel ficar pra trás, e tela nova já nasce assinada.
Na tela ela fica no fim da página, bem apagadinha, e não atrapalha nada: não cobre botão, não recebe toque e não aparece quando você manda imprimir a página. Medido na etiqueta de verdade: a assinatura ocupa de 292,4 a 295,0 mm numa folha de 297 mm, o rodapé acaba em 292 mm e o QR ficou intacto. 12 mutações de teste (tests/assinatura-mtx.test.mjs).
✅ Não precisa do Luan: é só tela.
🔧 CORRIGIDO: o romaneio parou de sair pelo sistema depois da última atualização. Aparecia "Não deu pra ler o histórico de romaneios — não emiti número novo. Confira a conexão" mesmo com a internet boa. Desculpe — foi defeito meu, da v2.37.495.
🔎 O que era: o conserto anterior passou a conferir o histórico no servidor antes de dar número (pra nunca mais repetir número), mas usou um caminho que só existe nos aplicativos, não no sistema. Resultado: a conferência falhava sempre e a emissão parava.
✅ Nada foi perdido nem numerado errado. A trava é do tipo "na dúvida não emite": como ela não conseguia conferir, não gerou número nenhum — nenhum romaneio saiu repetido nem furou a sequência. O aplicativo da Expedição não foi afetado e continuou emitindo normalmente o tempo todo.
O teste que deveria ter pego isso passava verde porque o ambiente de teste inventava um recurso que a tela real não tem — agora ele imita a página de verdade, e duas checagens novas acusam essa volta. 30 checagens e 8 mutações.
✅ Não precisa do Luan: é só tela.
🚚 O pedido que foi embora pela metade agora DIZ isso: "CARREGADO PARCIALMENTE · 1 de 3 paletes". Quando parte dos paletes já subiu no caminhão, o pedido continuava escrito só "Pronto p/ carregar" — do lado de fora ninguém via que uma parte já tinha saído. Agora, do lado do status, aparece um selo azul dizendo o estado e quantos paletes já foram, com as caixas embarcadas.
📍 Aparece na Carteira (PCP) e no Relatório, sozinho, assim que a Expedição bipa. Some sozinho quando o resto embarca — ali o pedido vira "Carregado", como sempre foi.
⚠️ Só conta palete que saiu em carga bipada. Baixa manual no Estoque PA tira a caixa do estoque mas não é carregamento — é a mesma regra que você pediu em 13/08, quando uma limpeza de PA marcou 7 pedidos como "Carregado" sem caminhão nenhum. ⚠️ Nada muda no status gravado: o selo é lido na hora do livro de saídas de palete, então nenhuma tela que decide pelo status (cronograma, laudo, romaneio, faturamento) muda de comportamento. A contagem de paletes é a mesma do selo "📤 2 de 3 paletes ainda no PA" que já existia — os dois nunca podem discordar na mesma linha. 19 checagens e 5 mutações de teste (tests/carregado-parcialmente.test.mjs).
✅ Não precisa do Luan: é só tela.
📦 O Mural ficava RESSUSCITANDO apontamento velho — a Coladeira 01 aparecia direto, com a máquina vazia. O cartão mostrava "TURNO ENCERRADO · sem apontar desde 13:37" com um pedido de 31 de julho, avisando que o app do operador não dava notícia há 547 horas (22 dias). Você destravava no 🔓 e no dia seguinte ele estava de volta.
🔎 Por quê: o 🔓 Destravar marca o apontamento como encerrado no servidor — mas o celular/tablet do operador continuava com aquele apontamento velho guardado dentro dele, e toda vez que o app publica alguma coisa ele reenvia TODOS os apontamentos que tem guardados, não só o da tela. O reenvio desfazia o seu destravar, calado. Conferido no servidor: o apontamento estava lá com o carimbo "PCP (destravar em massa)" e, ao mesmo tempo, marcado como não encerrado — a prova do desfazimento.
✅ Agora o app obedece o seu 🔓. Quando a liberação é mais nova que a última mexida naquele apontamento, o app adota o encerramento, avisa o servidor na hora e para de reenviar. Destravou, ficou destravado — e a Coladeira 01 se limpa sozinha, sem você precisar destravar de novo.
Quem ganha é sempre o carimbo mais NOVO: pedido que o operador pegou de volta depois do destravar continua com ele, apontamento com atividade posterior não é tocado, e o pedido que está ABERTO na tela nunca é mexido — ninguém perde o pedido da mão no meio do serviço. Nada é apagado: o parcial em caixas, os paletes e o tempo continuam guardados, igual ao fim de turno. 21 checagens e 8 mutações de teste. Conferido em segunda leitura por outro modelo, que achou dois furos na primeira versão do conserto (ela não curava o caso já quebrado e não avisava o servidor).
✅ Não precisa do Luan: é só tela. ⚠️ Os tablets precisam abrir o app uma vez pra pegar esta versão; depois disso o 🔓 segura.
🔎 No zoom grande a arte agora fica NÍTIDA de verdade. Na versão passada, pra folha não sumir, o desenho parava de crescer no limite que o tablet aguenta — e no zoom máximo ficava um pouco borrado. Agora, quando o zoom passa desse ponto, o app desenha só o pedaço que está na tela, na resolução cheia, por cima da folha. Como é só um pedaço, cabe folgado: a nitidez deixa de ter limite de zoom.
👀 Como funciona na prática: você amplia, solta o dedo e em seguida o pedaço que está aparecendo fica limpo — dá pra conferir código de barras, traço fino e letra pequena. Arrastando um pouco, continua nítido (o app desenha com uma folga em volta); indo pra longe na folha, ele redesenha o pedaço novo. Ao voltar pra folha inteira, some sozinho.
Medido no navegador de verdade, com o zoom no talo: o pedaço sai 4× mais nítido que o desenho da folha inteira, encaixado no lugar certinho (mesmo ponto, mesma cor) e some quando o zoom volta. O pedaço nítido nunca atrapalha o dedo (o toque continua sendo da folha de baixo) e só aparece pronto — nada de retângulo branco piscando. 20 mutações de teste (tests/arte-zoom-com-os-dedos.test.mjs).
✅ Não precisa do Luan: é só tela.
📈 O número do sensor agora sobe de pouquinho, em vez de dar saltos. Ele pulava de 10 em 10 por um motivo simples: o aparelho da máquina manda o dado a cada 5 segundos (medido: 5 s cravados, 14 envios seguidos), mas o sistema só ia buscar de 10 em 10 — cada leitura trazia dois envios de uma vez. Agora o sistema lê no mesmo ritmo em que o dado nasce, e o número ainda caminha até o valor novo em menos de um segundo, com uma desacelerada no fim.
⚠️ A animação nunca inventa número: ela vai do valor anterior até o que o sensor mandou e para nele. Não adivinha o meio do caminho pelo ritmo — isso poria na TV da fábrica uma produção que ninguém contou. Se o aparelho ficar mudo, o número simplesmente fica parado onde está, que é a verdade. 19 checagens novas, 5 mutações de teste.
🛡️ Um aparelho não apaga mais os romaneios dos outros. Em 21/08 o histórico foi sobrescrito: 6 romaneios sumiram e os números 1 a 6 foram reusados — a carga do KININO saiu com papel assinado "Nº 6" e o sistema passou a chamá-la de "Nº 5".
🔎 O que estava acontecendo: o histórico era uma lista só, e cada aparelho gravava a lista inteira que tinha na memória. Um computador aberto com uma cópia de dias atrás regravava tudo por cima — e o pior: ele fazia isso sozinho, ao ser aberto, sem ninguém emitir nada.
✅ Agora cada romaneio é um registro próprio. Quando um aparelho grava o dele, o servidor junta em vez de substituir. Provei no servidor: dois aparelhos que nunca se viram gravaram e os dois sobreviveram; do jeito antigo, o segundo sumia.
🔢 E o número agora vem do servidor, na hora de emitir — não da memória do computador. Era isso que fazia a trava de "esta carga já tem romaneio" falhar.
⚠️ MUDA UMA COISA NO SEU DIA: o sistema não emite romaneio novo sem internet. Se o servidor não responder, ele avisa e não imprime — antes o papel saía com um número que talvez nunca fosse registrado. A 2ª via continua saindo normalmente, mesmo offline.
Nada do histórico foi mexido: os 6 que sumiram e o número do KININO ficam pra uma decisão sua, depois — restaurar antes de fechar o buraco só seria apagado de novo. Eles estão guardados em cópia. 34 checagens e 6 mutações de teste, mais a prova no servidor de verdade.
🔧 Peça ao Luan uma linha a mais (pôr "romaneios" na lista de documentos que só aceitam junção): é o que faz o servidor recusar a gravação de um aparelho que ainda esteja com a versão velha. Sem migration, só restart.
🤏 Os três defeitos do zoom da arte no tablet, consertados. Depois que a pinça entrou (v2.37.492), sobraram três incômodos — e cada um tinha uma causa diferente:
✨ A tela piscava a cada zoom. Ao redesenhar, a arte era apagada primeiro e o desenho novo só chegava um instante depois — nesse meio-tempo ficava tudo branco. Agora o desenho é feito por fora e só entra na tela quando está pronto: troca sem piscar.
🔍 No zoom grande a arte SUMIA (e voltava ao diminuir). O aparelho tem um limite de tamanho pro desenho, e no zoom máximo a folha passava muito desse limite — o tablet então devolvia a folha em branco, calado. Agora o desenho para de crescer no limite que o aparelho aguenta: no zoom máximo fica um tiquinho menos nítido, mas não some mais.
↩️ O zoom voltava sozinho. Quando a barra do navegador aparecia/sumia, ou o teclado subia, o app entendia como "girou a tela" e reencaixava a folha inteira, jogando fora a ampliação. Agora só reencaixa quem ainda está na folha inteira: quem ampliou continua ampliado, e o botão FIT segue certo.
Medido no navegador de verdade: o ponto embaixo do dedo sai 0,1 px do lugar, zero piscadas no redesenho e o zoom no talo desenha (antes pedia 128 milhões de pontos e vinha em branco). 12 mutações de teste (tests/arte-zoom-com-os-dedos.test.mjs).
✅ Não precisa do Luan: é só tela.
🏷️ O romaneio que o expedidor manda pelo celular estava saindo SEM A LOGO. O quadrado da marca ia em branco e o papel dizia "JP EMBALAGEM" em vez de "JP Micro Ondulados" — enquanto o mesmo romaneio tirado aqui pelo sistema saía certinho. O cliente e o faturamento recebiam duas caras do mesmo documento.
🔎 Por quê: a logo é montada por uma função que mora no arquivo central do sistema, e os aplicativos não carregam esse arquivo. O app até já tinha o cadastro da marca à mão — faltavam duas linhas pra ele saber usar.
✅ A logo sempre esteve cadastrada (no cadastro da empresa) — não era falta de cadastro. Agora sai a logo e o nome de verdade no PDF do celular, igual ao do sistema.
O conserto é o MESMO par de linhas que o app da Qualidade, o da Manutenção e o Almoxarifado JPE já tinham — só a Expedição tinha ficado sem; não inventei nada novo. Empresa sem logo cadastrada continua caindo na marca desenhada, sem quebrar nada. 15 checagens e 3 mutações de teste.
✅ Não precisa do Luan: é só tela.
🤏 A arte da caixa agora se mexe com os dedos, no tablet. Pince pra dar zoom (o ponto que está entre os dedos fica no lugar, não foge), arraste com o dedo pra andar pela folha e dois toques pra aproximar naquele ponto — outros dois voltam pra folha inteira. Antes só davam os botões − FIT +, e o dedo não fazia nada: a tela da arte abre por cima de tudo e o app é travado contra o zoom do navegador, então a pinça do aparelho nunca chegava ali (era por isso que a foto da paletização dizia "pince pra dar zoom" e não pinçava).
🔍 Soltou os dedos, o desenho volta NÍTIDO. Enquanto a pinça está acontecendo a folha estica na hora (sem travar); ao soltar, o PDF é redesenhado no tamanho novo — ele é vetorial, então fica limpo em qualquer ampliação, que é o que o impressor precisa pra conferir código de barras e detalhe fino. Os botões − FIT + continuam iguais e passaram a valer também pra foto da paletização.
Num aparelho antigo, sem suporte aos gestos, nada muda e a dica "pince" nem aparece — o app não promete o que não faz. E o desenho passou a sair um de cada vez: dar pinça e apertar o + no mesmo instante fazia dois desenhos disputarem a mesma tela, que é como o visualizador ficava preto. 10 provas novas e 9 mutações de teste (tests/arte-zoom-com-os-dedos.test.mjs), mais a medição no navegador de verdade: o ponto embaixo do dedo saiu 0,0 px do lugar.
🔢 No Mural, o número grande do sensor some enquanto tem pedido rodando. O cartão mostrava "5.223 no total" ao lado do ritmo — esse é o acumulado de vida do aparelho, que nunca zera de propósito (é o que segura a produção numa queda de energia). Só que num pedido em andamento ele não é a produção daquele pedido, e a linha "neste pedido" logo abaixo já dá o número certo. Os dois juntos faziam quem olha a TV somar errado.
Quando a máquina está livre, sem ninguém apontando, o acumulado volta a aparecer — ali ele é o único número que existe, e escondê-lo deixaria o cartão sem informação nenhuma do sensor. 11 checagens novas.
🛑 O aviso de máquina parada agora tem o botão de registrar a parada nele. Quando o sensor avisa "máquina parada há X min", o operador registra ali mesmo, com um toque — abre a mesma lista de 12 motivos que já existia (esperando chapa, quebra de máquina, falta de papel, refeição…). Antes ele tinha que rolar a tela até o fim pra achar o 🛑 Parar, junto do Finalizar, bem na hora em que a máquina está parada.
🔒 O botão não aparece quando o sensor está "sem sinal". Ali ninguém sabe se a máquina parou ou se foi a rede — oferecer registrar parada faria o operador lançar uma parada que talvez não tenha existido.
Nenhum motivo novo, nenhuma tela nova: só o atalho. O 🛑 Parar de baixo e o botão do aviso chamam a mesma função — duas cópias da mesma ação sempre acabam diferentes, foi o que aconteceu com o excluir pedido. E o aviso só se redesenha quando o texto muda, senão o toque do operador cairia no vazio no meio da atualização. 19 checagens novas, 5 mutações de teste.
🎨 O cliente volta a aprovar só a arte. Como o senhor falou: faca e clichê não são coisa dele, são da JP com o fornecedor. As abas de faca e clichê saíram do link do cliente — ele vê a arte, aprova a arte, e pronto.
🔓 E, principalmente: elas pararam de segurar a caixa. Do jeito que estava, a caixa esperava um "sim" que o cliente nunca ia dar, porque ele nem via aquilo na tela — a caixa ficaria parada pra sempre. Agora, aprovou a amostra e a arte, a caixa está liberada e é só lançar o pedido, que já cadastra a caixa junto.
🔪 Faca e clichê continuam inteiros, do lado de cá: anexar o DXF, anexar o PDF do clichê, encomendar com a ficha pronta, mandar pro fornecedor e virar pedido de compra. Só deixaram de ser aprovação e viraram o que o senhor disse que são — vínculo: qual ferramenta é daquela caixa e de quem foi encomendada.
☑️ As duas caixinhas do registro agora dizem "vai encomendar faca" e "vai encomendar clichê" — servem pra a gente saber o que comprar, e não travam nada.
O PDF do clichê ganhou lugar próprio pra ser anexado, junto do DXF, no bloco da ferramenta. Nenhum arquivo de ferramenta sai pelo link do cliente — o DXF é o arquivo que a facaria usa pra cortar aço, e aquele link é aberto na internet. 24 checagens e 7 mutações de teste, todas reescritas pra afirmar a regra nova.
⚠️ Depende do Luan rodar o restart (sem migration).
⚖️ O peso do carregamento feito pelo sistema estava errado — e agora bate. Na tela de carregar caminhão e no peso que vai gravado na carga (o que aparece no WhatsApp do motorista e no relatório de viagens), a caixa era procurada só pelo código, sem olhar o cliente.
🔀 Dois problemas numa linha só: (1) seis códigos existem em mais de um cliente (CX 01 é da GRANJA HATTORI, da KIMETAIS e da KININO), então entrava o peso da caixa do cliente errado; (2) quando o código do pedido não é o mesmo do cadastro ("KININO 29" × "Cx 29"), não achava nada e o peso simplesmente não somava.
📊 Medido nas cargas de verdade: 3 estavam erradas — duas mostravam 0 kg (2.528 kg e 3.000 kg de verdade) e uma marcava 4.581 kg quando eram 5.525 kg. No total, 6.471 kg que não apareciam.
Agora é a mesma busca do romaneio (pelo pedido primeiro, código depois) — e é uma conta só: a tela, a mensagem do motorista e o relatório nunca mais podem discordar. Caixa de outro cliente continua proibida de entrar, e caixa sem peso cadastrado continua somando zero em vez de virar número inventado. 15 checagens e 4 mutações de teste.
✅ Não precisa do Luan: é só tela. Cargas antigas mantêm o peso que foi gravado — este conserto vale das próximas em diante.
📦 Pra não deixar palete pra trás: agora dá pra conferir o estoque na hora de carregar. Na tela da carga, embaixo, tem "📦 Conferir o que tem no estoque (opcional)": escolhe o cliente e depois o modelo da caixa, e o app mostra o que aquele modelo tem no PA.
🔢 Ele conta enquanto o senhor carrega: "Cx 29 — 5 de 10 paletes nesta carga · faltam 5 (2.630 cx) no PA". Cada palete aparece marcado: ✅ os que já entraram e ⬜ os que continuam no estoque. O que ficar pra trás aparece de novo no próximo carregamento, sozinho.
📋 É por MODELO, não por cliente — o mesmo cliente costuma ter vários, e cada modelo pode ter mais de um lote. Palete de lote diferente vem marcado (L2) pra não confundir dois lotes da mesma caixa.
🤖 Não precisa escolher nada: assim que o primeiro palete é bipado, ele já abre no cliente e no modelo daquele palete. Mas se o senhor escolher na mão, ele respeita a sua escolha e não muda mais sozinho.
É só pra olhar — o palete continua entrando na carga pelo QR (ou pelo "✋ Marcar manualmente" que já existe). Uma lista que carregasse com um toque deixaria o papel dizer que um palete embarcou sem ninguém ter olhado pra ele na doca. Palete que já saiu do PA não aparece, e a lista usa a mesma conta do "Marcar manualmente" — as duas nunca discordam. 22 checagens e 5 mutações de teste.
✅ Não precisa do Luan: é só tela.
👀 O mesmo caminhão aparecia duas vezes — e agora a tela explica. O ACH9A34 estava em "carregando agora" (1 palete) e logo abaixo em "fechadas hoje" (15 paletes, romaneio emitido). Não eram duas cargas: o expedidor bipou 1 palete, começou outra carga 3 min depois e rebipou o mesmo palete lá. A primeira ficou pra trás.
🔎 Agora o cartão diz o porquê: "⚠️ Outra carga deste caminhão foi fechada às 16:28, depois desta — esta aqui provavelmente ficou pra trás". E o botão "✔️ Não está carregando" aparece na hora, sem precisar esperar as 14 h.
🧠 Não é chute, é prova. Um caminhão não pode estar carregando agora se uma carga dele foi fechada mais tarde. Quando ele começa uma viagem nova de verdade, a carga nova é bipada depois do fechamento da anterior — e aí a tela não acusa nada.
🚪 E a porta que deixava isso acontecer foi fechada. Começar uma carga pela escala sempre avisou "você vai perder o que já bipou"; a tela de carga avulsa não avisava nada — deixava a anterior pendurada em silêncio. Agora as duas fazem a mesma pergunta, escrita num lugar só.
Encerrar continua guardando o registro, sem mexer em estoque nem em pedido, e nunca encosta na carga que virou romaneio. 30 checagens e 8 mutações de teste.
✅ Não precisa do Luan: é só tela.
📡 O sensor da máquina agora ajuda o operador — sem mandar nele. No app do operador, logo abaixo do campo "Caixas produzidas", aparece quanto o sensor contou neste pedido. É só conferência: ele continua digitando o número que contou. Preencher o campo sozinho apagaria a segunda opinião, e é justamente a diferença entre os dois números que denuncia problema — foi assim que descobrimos hoje que o sensor da Slotter está contando errado.
⚠️ Aviso de máquina parada. Se o sensor está no ar e o número dele não sobe há 1 minuto, a tela avisa "máquina parada há X min". Se o aparelho emudecer, a tela diz "sem sinal" em vez de acusar a máquina — pode ser a rede, e aí ninguém tem como saber se ela parou. E se o operador já registrou a parada, o aviso não repete: ele acabou de dizer que parou.
🔢 Uma conta só pros dois lugares. O "quanto o sensor contou neste pedido" passou a morar num arquivo só, lido pelo Mural e pelo app do operador. Antes a conta existia só no Mural; se eu tivesse copiado ela pro app, um dia as duas telas mostrariam produções diferentes do mesmo pedido e ninguém saberia qual acreditar.
Máquina sem sensor: tela idêntica à de antes — nada aparece. E enquanto o sensor da Máq. B Slotter não for limpo e regulado, o número dele não vale: em 21/08 ele marcou 5.647 peças/h com a máquina parada, e com ela rodando marcou até menos. A tela está pronta; falta o aparelho. 23 checagens novas e 8 mutações de teste.
🔕 Tirei também a caixa "PRODUTO PRONTO — FALTA IMPRIMIR ETIQUETA" que subia no meio da tela. Era a irmã da do romaneio: cobria a tela inteira e voltava a cada 10 minutos. Acabou — igual à de ontem.
🖨️ O botão 🖨️ Etiquetas continua fazendo tudo. O número vermelho nele continua mostrando quantos lotes faltam imprimir, e clicando nele a lista abre igualzinha, com o 🖨️ Imprimir etiquetas e o ✔️ Já imprimi de cada lote. A diferença é só uma: agora ela abre quando o senhor quer, não sozinha.
Conferido no navegador contra a versão de antes: antes a caixa subia sozinha no relógio de 1 minuto, agora não sobe — e o clique no botão, a lista, os dois botões de cada lote, o fechar e o número vermelho continuam funcionando igual.
✅ Não precisa do Luan: é só tela.
🔕 Tirei a caixa "CARGA FECHADA — FALTA IMPRIMIR O ROMANEIO" que subia no meio da tela. Ela cobria a tela inteira e voltava a cada 10 minutos enquanto o romaneio não saísse, atrapalhando quem nem é da expedição. Acabou.
✅ O aviso na hora certa continua. Quando o expedidor termina de carregar, o bloco âmbar segue aparecendo dentro da própria tela de "Carregamento finalizado", com um botão 🖨️ Imprimir romaneio por cliente da carga. É o momento em que a pessoa ainda está ali — e esse não cobre nada.
🚥 E o painel 🚚 Expedição ao vivo continua marcando. A carga fechada sem romaneio segue com o selo laranja "fechada, falta romaneio", e só fica verde 🟢 quando o papel sai. É lá que a cobrança mora agora, sem pular na frente de ninguém.
Conferido no navegador com a mesma carga da tela: antes a caixa subia sozinha, agora não sobe — e o bloco da tela de finalizar aparece igualzinho, com o botão funcionando.
⚠️ O aviso de etiqueta ("produto pronto, falta imprimir etiqueta") é outro, e não foi mexido. Se quiser esse fora também, é só falar.
✅ Não precisa do Luan: é só tela.
🚛 Dá pra tirar da tela o caminhão que não está carregando mais. Em "Carregando agora" apareciam 5 caminhões com a doca vazia — um deles (FBW4G22) aparecia carregando enquanto a carga de verdade dele já tinha virado o romaneio nº 6. Agora, no cartão de quem está parado há mais de 14 h, tem o botão "✔️ Não está carregando".
🔒 Ele guarda, não apaga. A carga sai da lista mas o registro fica gravado (com quem encerrou e quando). Nada é mexido no estoque nem em pedido nenhum — conferi no servidor: carga que não foi finalizada nunca baixou caixa do estoque. E carga já fechada (a que virou romaneio) não tem esse botão e não pode ser encerrada por ele de jeito nenhum.
🧹 E a raiz do problema foi consertada: 4 daqueles 5 eram cascas vazias — alguém abriu a tela de carregar, escolheu o caminhão e voltou atrás, e aquele registro ficava pendurado pra sempre. Agora, ao começar outra carga, a anterior vazia some sozinha (nas duas portas: pela escala e no avulso). Carga com palete já bipado continua protegida, pedindo confirmação como sempre.
O botão só aparece na carga esquecida (mais de 14 h parada): num caminhão que está carregando de verdade, seria um clique errado esperando pra acontecer. E o painel continua mostrando a carga parada em vez de escondê-la — esconder calado foi o defeito do Mural que ficava verde a noite inteira. 24 checagens e 5 mutações de teste.
✅ Não precisa do Luan: é só tela.
📡 Sensor de contagem na máquina (fase 1). O contador físico da Máq. B Slotter (sensor fotoelétrico + ESP32) agora fala com o sistema. O cartão da máquina no Mural ganhou uma linha 📡 com o que o sensor contou — ao lado do que o operador apontou, nunca no lugar dele.
🔢 Quantidade por pedido. Quando o operador inicia a produção, o sistema guarda quanto o sensor marcava naquele instante; a quantidade do pedido é a diferença. O acumulado do sensor nunca zera, pra não perder produção numa queda de energia.
▶️ Botão "produção ao vivo" no cartão. Escolhe, por máquina, se a barra e o ritmo vêm do sensor ou do apontamento. Só a TELA muda — o registro do pedido continua sendo o do operador.
⚠️ Avisa quando o sensor está contando e não existe apontamento aberto — produção saindo sem registro.
Máquina sem sensor: o cartão fica idêntico ao que era.
✅ Não precisa do Luan: é só tela.
🔔 O romaneio incompleto agora AVISA antes de sair. Se alguma caixa não for achada no cadastro, o sistema pergunta antes de imprimir: mostra qual caixa, quantas caixas são e diz que o papel vai sair com "—" na medida e na qualidade (e sem a coluna de peso). Foi assim que ~3.000 kg foram embora sem ninguém ver.
✅ Avisa, não trava. É só uma pergunta — quem responde "sim" imprime igual, porque o caminhão está na doca e o papel tem que poder sair. Quem responde "não" não queima o número: nada é gravado e nada é impresso, dá pra ir amarrar a caixa no pedido e voltar.
📱 No app da Expedição o aviso aparece na tela, junto do botão de mandar o PDF — lá não pergunta, porque o expedidor não tem como resolver na hora; ele avisa o PCP.
O aviso não dispara por peso faltando sozinho: ~23% das caixas não têm peso cadastrado, e um aviso que aparece sempre deixa de ser lido justo no dia em que importa. 21 checagens e 5 mutações de teste.
✅ Não precisa do Luan: é só tela.
📇 Na hora de encomendar, os fornecedores daquela ferramenta vêm em cima — e com o telefone escrito do lado. Escolhendo a faca, aparece primeiro o grupo 🔪 Fornecedores de faca; escolhendo o clichê, o de clichê. E cada um mostra o contato: "MTX MATRIZES — (17) 98888-1122". Quem não tem telefone nem e-mail aparece com ⚠️ sem contato, pro senhor não escolher e só descobrir depois.
🔁 Quem fornece os dois aparece nos dois. Se a mesma casa faz faca e clichê, é só marcar as duas categorias na ficha dela em Cadastros ▸ Fornecedores — ela sobe no grupo de cima das duas vezes.
Ele agrupa, não esconde: ninguém some da lista. E se nenhum fornecedor estiver marcado naquela categoria, ele mostra todos e avisa que é pra marcar — hoje, por exemplo, nenhum está marcado como Faca, porque as facarias ainda não foram cadastradas.
📷 A etiqueta do palete saía com o QR CORTADO AO MEIO quando era impressa pelo celular. Aconteceu na ALPACK 23532 (15 paletes): na tela o QR aparecia inteiro, mas o papel que saía da impressora vinha com metade dele faltando — e palete com QR pela metade não bipa na Expedição.
🔎 O que estava acontecendo: abri o PDF que saiu do iPhone e medi por dentro. A moldura azul do QR foi desenhada no lugar certo, mas o QR em si foi desenhado 4,5 cm mais pra baixo — caindo pela metade fora da folha. O QR era o único pedaço da etiqueta posicionado "no meio da caixa" em vez de numa medida fixa em milímetros; todo o resto da etiqueta usa milímetros, e todo o resto saiu no lugar certo.
📏 Agora o QR também é em milímetros, exatamente na mesma posição de sempre (26 mm x 209,5 mm da etiqueta) — só que sem depender de o celular calcular o meio da caixa na hora de montar a folha. Na tela e no computador nada muda: conferi que a posição bate até a quarta casa do milímetro.
📄 E acabou a folha em branco: agora é UMA etiqueta por página. No mesmo PDF do celular saíam 30 páginas pra 15 paletes — uma quase em branco depois de cada etiqueta. É que o iPhone não obedece "margem zero": ele impõe a margem dele e encolhe a folha pra caber na largura, e sobravam ~5 mm que iam pra página seguinte. A etiqueta passou a ser desenhada 5% menor que o papel (199,5 × 282,2 mm), então cabe inteira com folga. Conferi: 3 etiquetas = 3 páginas.
Vale nos dois lugares que imprimem etiqueta: o app do operador e a reimpressão pelo sistema. O QR fica com 6,5 cm (era 6,8 cm) — continua grande pra ler da empilhadeira. 22 checagens e 8 mutações de teste (tests/etiqueta-qr-cortado.test.mjs).
✅ Não precisa do Luan: é só tela.
🔁 A 2ª via dos romaneios que já saíram mudos agora sai completa. O conserto de antes valia pros romaneios novos; os que já estavam gravados no histórico — o nº 6 do KININO e o nº 4 da TANGARA — voltariam com o mesmo tracinho pra sempre, porque a reimpressão copia o que ficou guardado. Agora, na hora de reimprimir, o que estiver faltando é buscado no cadastro de hoje.
🔒 O que o cliente já assinou NÃO muda. Número, data, nº de paletes, nº de caixas e a divisão dos paletes continuam sendo os gravados na emissão — só entra o que estava em branco (medida, qualidade e peso). Uma 2ª via que discorde da 1ª é pior que uma que fala menos.
Se não achar a caixa com segurança, continua "—" — nada de chute: caixa de outro cliente não entra, e nº de pedido que aponta pra duas caixas diferentes não escolhe nenhuma. O registro no histórico também não é reescrito; só a folha que sai da impressora. 16 checagens e 5 mutações de teste.
✅ Não precisa do Luan: é só tela.
📄 O romaneio voltou a sair com a MEDIDA, a QUALIDADE e o PESO. O romaneio nº 6 da KININO foi com o caminhão com um tracinho no lugar da medida e da qualidade, e sem a coluna de peso — faltavam ~3.000 kg no papel, com o cadastro da caixa certinho.
🔎 O que estava acontecendo: o romaneio procurava a caixa pelo código, e o código do pedido nem sempre é o mesmo do cadastro. Esse pedido veio do Sectra como "KININO 29" e a caixa está cadastrada como "Cx 29" — não bate, não acha, o papel sai mudo. Conferi as 22 cargas: 47 dos 134 paletes caíam nisso (KININO 29, 42 e 06, FUNDO M da REVAL, 07 FLOPS da TANGARA), todos com o cadastro certo, só com o nome diferente.
🔗 Agora ele segue o vínculo de verdade. O pedido já guarda qual caixa é (não só o nome dela), e o palete já sabe de que pedido veio. É por aí que o romaneio acha a caixa agora. O código continua valendo de reserva, pros paletes antigos.
⚖️ O peso da carga na tela do expedidor foi junto, senão a tela diria "20 paletes sem peso" e o papel imprimiria 3.000 kg — dois números da mesma carga.
Nada de chute: caixa de outro cliente continua proibida de entrar no papel, e pedido sem caixa amarrada segue saindo com "—" (campo em branco pede cadastro; número errado ninguém questiona). 16 checagens e 4 mutações de teste.
⚠️ Ainda ficam de fora 8 paletes — os pedidos KININO 42 e KININO 06 não têm caixa amarrada. Basta abrir o pedido e escolher a caixa (ou acertar o código no cadastro) que eles passam a sair completos também.
✅ Não precisa do Luan: é só tela, sem mexer no banco nem na API.
📧 Agora o próprio sistema manda o e-mail pro fornecedor. Além do WhatsApp e do copiar, tem o botão "📧 Mandar por e-mail": o servidor monta a ficha e envia direto, sem passar pelo seu programa de e-mail. O endereço sai do cadastro do fornecedor — o senhor não digita e-mail nenhum na hora de mandar.
✅ E se o e-mail não sair, ele diz. Se o envio não estiver ligado no servidor, aparece o aviso e a encomenda não é marcada como mandada — antes disso, um e-mail que falhasse em silêncio deixaria a fábrica esperando uma ferramenta que a facaria nunca soube que era pra fazer.
👀 A prévia da tela virou a mensagem de verdade. Ela é montada pelo servidor e mostrada aqui — o que o senhor lê antes de mandar é, letra por letra, o que o fornecedor recebe. Antes a tela montava a dela e o servidor montaria outra.
Por que assim e não mais simples: uma porta que aceitasse "manda este texto para este endereço" seria um jeito de usar o sistema pra disparar mensagem pra qualquer um. Aqui o destinatário e o texto nascem os dois no servidor, a partir do que está gravado. 25 checagens e 9 mutações de teste.
⚠️ Depende do Luan rodar o restart (sem migration). Enquanto ele não roda, a tela de encomenda não monta a ficha e avisa isso — o WhatsApp volta junto com o resto.
🛒 Encomendou a faca ou o clichê, o comprador já fica sabendo. Na mesma tela de mandar a ficha tem agora "🛒 mandar também pro comprador", marcado. O pedido cai em 💰 Centro de Custo ▸ Pedidos de Compra com o fornecedor, a caixa e o número da ferramenta — e segue o caminho de sempre: o comprador negocia, marca recebida, e cai no Lançamento pra dar baixa.
👤 Já vai com a categoria e o cliente certos, então a despesa volta como clichê ou faca (que ficam fora do custo do mês, porque quem paga é o cliente) e aparece no relatório de clichê/faca por cliente. Sem isso ela voltaria como manutenção.
Não criei uma segunda ordem de compra. A fábrica já tem a esteira inteira e testada — pôr outra, com numeração própria, daria dois números de ordem pro mesmo fornecedor. O que entrou foi só o atalho: o pedido nasce lá, no formato que o comprador já usa, e quem numera a OC continua sendo ele.
⚠️ O valor do orçamento NÃO vira o valor da compra. O que está no orçamento é o que se cobra do cliente (tem margem dentro); usar como custo faria o sistema registrar como despesa um dinheiro que ninguém pagou. Ele vai junto como referência pro comprador negociar, e o custo é o que ele preencher. 18 checagens novas e 7 mutações de teste.
⚠️ Depende do Luan rodar o restart (sem migration).
📤 A encomenda da faca e do clichê agora sai pronta do sistema. No Desenvolvimento, ao lado do número da ferramenta, tem "📤 mandar a ficha": o senhor escolhe o fornecedor e o sistema monta a encomenda inteira — nº FC-/CL-, cliente, caixa, medidas internas e da chapa, composição, onda, gramatura, coluna, cores e o link do arquivo. Vai pelo WhatsApp (abre a conversa com o texto pronto) ou pelo copiar e colar. O fornecedor não precisa mais ligar perguntando medida.
📐 E o DXF da faca ganhou onde ser anexado — não existia tela nenhuma pra isso no sistema inteiro. Ele é interno: vai pra facaria, nunca pro link do cliente (lá vai a prévia em PDF).
🔗 Fica registrado de quem foi encomendada, quando e por onde, no histórico da caixa — e é disso que a ordem de compra vai sair na próxima etapa.
A ficha nunca inventa medida: campo que a fábrica não tem sai FORA dela, em vez de virar um "—" no meio de um número que o fornecedor lê pra cortar aço. E ela avisa antes o que falta — sem DXF anexado, sem número reservado ou com o fornecedor sem contato no cadastro, ela diz o que é, em vez de deixar mandar pela metade. 23 checagens novas e 7 mutações de teste.
⚠️ Precisa do senhor: hoje temos 3 fornecedores cadastrados, nenhum com telefone, e a facaria não está lá. O WhatsApp só funciona pra quem tiver o número em Cadastros ▸ Fornecedores.
⚠️ Depende do Luan rodar o restart (sem migration).
🔒 A caixa só vira pedido com o pacote aprovado — e o senhor escolhe caixa a caixa o que ela precisa. Na tela de registro, ao lado de "vai mandar amostra física" e "tem impressão (arte)", entraram mais duas: "vai ter faca nova" e "vai ter clichê". O que estiver marcado, o cliente tem que aprovar antes de a caixa ser liberada.
💡 E ele já sugere sozinho: escreveu as cores, marca o clichê; escolheu corte e vinco, marca a faca. Se o senhor desmarcar, ele não teima — quem sabe se a faca vai ser reaproveitada é o PCP.
📣 O aviso passou a dizer o que falta de verdade. Antes, ao tentar lançar o pedido cedo demais, aparecia sempre "falta o cliente aprovar orçamento, amostra e arte" — mesmo quando o que faltava era a faca. Agora fala a mesma coisa que está escrita no cartão da caixa.
🔗 A caixa criada fica amarrada à proposta. Quando o cadastro nasce do Desenvolvimento, a proposta passa a guardar qual caixa é — antes o reencontro dependia do código + cliente, e bastava renomear a caixa pra o histórico dela se perder, calado.
Nada do que já está no funil trava: caixa antiga não tem essas marcas e continua andando igual. A conta de "o que esta caixa exige" passou a morar num lugar só, lido pela tela e pela porteira do pedido — duas contas fariam a tela dizer "liberada" e o pedido ser recusado. 17 checagens novas e 7 mutações de teste.
⚠️ Depende do Luan rodar o restart (não tem migration nova desta vez).
📦 O cliente passa a aprovar o PACOTE, não só a arte. No link que a JP manda, a caixa agora tem abas: 🎨 Arte · 🔪 Faca · 🖨️ Clichê. Ele aprova cada uma, ou desenha com o dedo em cima e pede alteração — do mesmo jeito que já fazia com a arte. Quando as três estão aprovadas, aparece "✅ Pacote aprovado".
🖨️ Do lado de cá, no Desenvolvimento, a faca e o clichê ganharam os mesmos botões que a arte já tinha: anexar, ver a versão atual, mandar a v2 quando o cliente pedir mudança, e excluir. Cada peça tem a sua versão — mandou a faca v2, o "sim" da v1 não vale mais e o cliente é chamado pra olhar a nova.
Nada do que está andando hoje trava: caixa sem faca e sem clichê anexados continua liberando igual, porque só cobra o que foi mandado. Quem tem só arte nem vê aba — a tela fica idêntica à de antes. O arquivo DXF da faca não sai pelo link do cliente (ele vê uma prévia em PDF); o DXF é o que vai pra facaria, na próxima etapa. 18 checagens novas e 7 mutações de teste.
⚠️ Depende do Luan rodar o migrate + restart no servidor. Enquanto ele não roda, a arte, a amostra e o orçamento continuam funcionando; a faca e o clichê avisam que ainda não estão liberados.
🖼️ Pedido de clichê ou faca agora pergunta o cliente. Ao escolher Clichê (ou Faca) no pedido de compra, abre sozinho o campo do cliente — porque quem paga é ele. O clichê fica atrelado pra consulta depois, e o cliente aparece na lista do pedido e no acompanhamento.
🐛 E consertei um buraco que ninguém tinha visto ainda: a compra que voltava do comprador era sempre lançada como Manutenção. Ou seja, um clichê que o senhor pedisse por ali voltaria como manutenção, entraria no custo do mês (clichê e faca ficam de fora, quem paga é o cliente) e perderia o cliente. Agora volta na categoria certa.
O nome do cliente casa exato: escrever "K" não vira "KININO" — clichê pendurado no cliente errado seria consulta errada pra sempre; quando não bate, guarda o que foi digitado sem inventar vínculo. Pedido vindo da Manutenção ou do Almoxarifado continua caindo em Manutenção, igual antes. 11 checagens novas.
🦾 Escolheu o fornecedor? O sistema já mostra o que ele te vende. No pedido de compra, ao digitar o nome do fornecedor aparece a lista do que ele já forneceu — com o preço da última compra e quando foi. Um clique no ➕ põe o produto na lista, já com o balde inteiro. É a recompra em dois toques.
📦 Também mostra o que ele fornece mas você nunca comprou — vem marcado como "nunca comprado por aqui", pra o senhor saber que existe a opção.
Não é cadastro novo pra ninguém preencher: sai do histórico de compras e do cadastro do almoxarifado, então se corrige sozinho conforme a fábrica compra. O nome do fornecedor casa exato (maiúscula e espaço não atrapalham, mas "DAL" não vira "DAL COLOR") — fornecedor trocado viraria recompra do produto errado. Consertei junto um detalhe: o fornecedor, a observação e a urgência já digitados não se perdem mais quando o senhor põe outro item na lista.
🎨 Agora o pedido de compra se monta pelo ESTOQUE. Escolhe "Tinta" e aparecem as cores cadastradas já dizendo quanto tem de cada uma — "AZUL 06 — tem 0 kg (mín 2) ⚠️ abaixo do mínimo". O senhor vê o que está faltando na hora de pedir, sem abrir outra tela.
🛒 Vários itens no mesmo pedido. Põe cor por cor na lista e manda tudo junto pro comprador, numa ordem só. Ao escolher a tinta ele já sugere o balde inteiro (20 kg), que é como se compra.
✏️ Produto que ainda não existe também pode ser pedido — é só digitar o nome. O cadastro se faz na hora de dar entrada.
O saldo que aparece é o MESMO do almoxarifado (não é uma segunda lista), e fica gravado no pedido quanto havia no momento em que o senhor pediu. Se a hora de mandar falhar, a lista montada não se perde. 6 checagens automáticas novas.
🛒 Tela nova: "Pedidos de Compra", dentro de 📒 Financeiro. O senhor escreve o que a fábrica precisa, a quantidade, um fornecedor sugerido e a urgência — e o pedido vai direto pro app do comprador, na mesma fila das peças de manutenção e do almoxarifado.
🔄 Agora a volta está fechada: o comprador negocia o preço e manda pro fornecedor; quando ele marca que chegou, a compra aparece sozinha no Lançamento de Insumos pra dar baixa (custo do mês + estoque). O senhor acompanha o andamento na própria tela: com o comprador · comprada · chegou.
💰 Preço quem põe é o comprador. O pedido sai daqui sem valor de propósito — quem negocia é ele, e chutar um número aqui viraria custo errado lá na frente.
Cuidado que tomei: gravar um pedido novo relê a lista de ordens do comprador no instante da gravação, pra não atropelar o que ele acabou de criar. E se a leitura falhar, o sistema não grava nada e avisa — o que o senhor digitou continua na tela. 13 checagens automáticas novas.
🛒 Quando o comprador marca a compra como RECEBIDA, ela cai sozinha na sua caixa "Aguardando baixa". O senhor não precisa mais digitar de novo o que já passou pelo app de Compras — a ordem aparece ali, com o número da OC e o fornecedor, marcada com uma tarja "veio das Compras".
✅ Daí pra frente é o caminho de sempre: "Dar baixa" → confere → "Lançar". Entra no custo do mês e soma no estoque igual já fazia.
⚠️ OC sem valor não vira R$ 0,00. Se o comprador não preencheu o valor, ela aparece dizendo "sem valor" e o senhor digita antes de lançar — o sistema não inventa número.
🔒 Compra antiga não volta. Só entram as recebidas de 19/08/2026 em diante. As de julho que já estavam lá ficaram de fora de propósito, pra ninguém lançar de novo o que já foi pago.
O sistema só LÊ as ordens de compra — quem manda nelas continua sendo o app de Compras, e nada é escrito lá de fora. Cada compra carrega o carimbo da OC que a gerou, então não tem como entrar duas vezes no custo. 11 checagens automáticas novas.
🩹 A 2ª via do romaneio estava saindo diferente da 1ª.
A divisão dos paletes ("3 × 1.000 + 1 × 300") saía na hora de emitir, mas sumia na reimpressão — o histórico guarda os itens campo a campo e esse campo novo não tinha sido incluído. Duas folhas do mesmo romaneio dizendo coisas diferentes, na mão do cliente. Corrigido nos dois lugares que emitem: o sistema e o app da Expedição.
📄 Romaneio emitido antes disso reimprime como sempre foi, sem a linha nova: ninguém guardou como aqueles paletes estavam montados, e 4 paletes com 3.300 caixas tanto podem ser 1.000+1.000+1.000+300 quanto 900+900+900+600. Chutar seria mentir num papel que o cliente assina.
🗓️ "Pedido feito há quantos dias" estava contando errado — o senhor mesmo pegou. Ele contava blocos de 24 horas em vez de dias do calendário: um pedido feito ontem às 21h ainda dizia "hoje" às 8h da manhã seguinte.
⚠️ O que isso atrapalhava de verdade: o aviso amarelo que avisa quando um pedido passa de 7 dias esperando saía um dia atrasado. Agora conta pelo relógio da parede, certinho.
Ficaram 3 checagens automáticas novas pra isso não voltar (pedido de ontem, do mesmo dia e de uma semana atrás).
📒 No menu, "Custos" agora se chama "Financeiro". É o mesmo lugar de sempre, com as mesmas telas dentro (Lançamentos, Contas & Previsão, Ponto de Equilíbrio, Conciliação, DRE) — só o nome mudou, a pedido do senhor.
Só o rótulo do menu. Nada foi movido, nenhuma permissão mudou e nenhum acesso se perdeu — por dentro o módulo sempre se chamou "financeiro".
📦 O orçamento também diz como os paletes ficam divididos.
Ele dizia só "3 paletes" — e 3 paletes de 750 não são 2.250 caixas quando o pedido é de 1.600. Agora, embaixo do número, sai "2 × 750 + 1 × 100": o cliente vê que o último palete vai parcial antes de fechar o pedido.
🗣️ É a MESMA frase do romaneio (v2.37.461), escrita pelo mesmo código de propósito — o cliente compara os dois papéis, e duas maneiras de escrever a mesma coisa viram dúvida.
🤐 Só fala quando o último vai parcial. Dando tudo cheio, o documento já diz "2 paletes" e "750 caixas por palete" — repetir "2 × 750" seria só barulho.
👀 A tela do orçamento mostra a frase enquanto o senhor digita, para ver exatamente o que o cliente vai ler.
Vale nos quatro documentos: a nota do sistema, o WhatsApp, o app do vendedor e o link que o cliente abre pra aprovar. O link do cliente só mostra depois do reinício do servidor (Luan).
📦 O romaneio agora diz COMO os paletes estão montados.
Ele mostrava só o total — "4 paletes · 3.300 caixas" — e parava aí. Só que 4 paletes podem ser 4 cheios ou 3 cheios e 1 pela metade, e é justamente isso que o conferente confere na doca e o cliente recebe. Agora, embaixo do número de paletes, sai "3 × 1.000 + 1 × 300" — na tabela e também no canhoto que o cliente assina.
🔢 O número não é conta nossa: sai do que cada palete tem de verdade (o que o expedidor bipou). No romaneio tirado do planejamento, sai dos paletes cheios + o parcial que o plano já separa; e se o Estoque PA souber os paletes de verdade, valem os dele.
🤐 E cala quando não fecha: se algum palete estiver sem a quantidade, ou se a soma não bater com o total da linha, a linha simplesmente não sai. Papel que se contradiz é pior que papel que fala menos — a mesma regra do peso, que sai "—" quando a caixa não foi achada com segurança.
Vale nos dois lugares que emitem romaneio: o sistema e o app da Expedição. Romaneio antigo continua saindo igual, só sem a linha nova.
✔️ Conferiu a chapa no Mutirão? O pedido SAI da lista. Antes ele ficava lá mesmo depois de corrigido, e parecia que não tinha adiantado nada. Agora o número que você digita vale como conferido: o pedido sai do Mutirão e volta a contar nas médias do relatório, com o número certo.
🧠 Por que isso é justo: a regra que jogava o pedido pra lá ("a chapa é mais de 1,5× o pedido") é uma desconfiança — o sistema chuta que ali foi lançado um lote inteiro num pedido partido. Quem foi no papel e disse o número desfez a dúvida; palpite não ganha de gente.
⚠️ Uma coisa NÃO é perdoada: se a máquina de depois continuar apontando mais caixa do que entrou, o pedido fica na lista — esse dado é impossível e alguém precisa arrumar de verdade. Quando é isso que segura, o aviso na tela passa a dizer o novo motivo, na hora de gravar.
🔁 A conferência vale pro número conferido, só. Se a onduladeira lançar a chapa daquele pedido de novo, com outro número, a conferência deixa de valer sozinha (ela falava do número velho) e o pedido volta pra lista — sem ninguém precisar lembrar de nada.
👀 Fica marcado: na lista "Pedido a pedido", abrindo a linha, aparece "✔️ chapa conferida na mão por Fulano em 19/08" — pra ninguém confundir com o que a onduladeira lançou.
Só a tela — não precisa do Luan. O teste automático cresceu junto (tests/mutirao-chapa-grava.test.mjs).
🧰 Mutirão da Perda por Etapa: "eu coloco a quantidade e ele não grava". Eram dois problemas em cima do mesmo campo, e os dois estão consertados.
1️⃣ O número digitado sumia do campo. Essa tela se redesenha sozinha o tempo todo (cada apontamento que chega do operador, cada atualização da carteira). A cada redesenho o campo voltava vazio — e quem clicava no ✔️ logo depois estava gravando um campo em branco. Agora o número que você digitou fica no lugar (e o cursor volta pra ele), até você gravar.
2️⃣ A correção voltava pro número velho em segundos. Você gravava 329, o servidor aceitava, e a tela puxava a foto antiga do servidor (que demora um pouco pra ficar pronta) e desfazia sozinha: aparecia 340 de novo, como se nada tivesse acontecido. Agora a chapa corrigida segura até a foto do servidor alcançar — a mesma regra que já protege o status ("a última edição na mão vence").
⚠️ Digitar o MESMO número que já está lá agora avisa. Se você digitar 340 num pedido que já tem 340, a pergunta de confirmação diz na cara: "esse é o mesmo número que já está gravado — a linha vai continuar igual". Era o jeito mais fácil de achar que não gravou.
📋 Uma coisa que NÃO mudou, e é bom saber: corrigir a chapa não tira o pedido da lista quando a chapa continua muito maior que o pedido (mais de 1,5×). No 23723 · FK GRUPO 35230, por exemplo, o pedido é de 200 caixas e a chapa certa é 329 — ele continua no Mutirão, só com o número certo. Pra tirar de vez, é o 🚫.
Só a tela — não precisa do Luan. Ficou um teste automático com as regras (tests/mutirao-chapa-grava.test.mjs).
🚚 DUAS VIAGENS NO MESMO DIA: dá pra carregar o motorista que ainda não voltou. Até agora, quando o motorista saía numa entrega, ele sumia da lista da tela de carregamento — e ninguém conseguia deixar a 2ª carga dele pronta esperando ele chegar. A saída era marcar "✓ Voltou" com o caminhão ainda na estrada, e aí o escritório passava a ver ele na fábrica sem estar.
✅ Agora ele aparece, num grupo separado chamado "🚚 Em viagem — ainda não voltaram", com o aviso no nome: "em viagem há 2h30".
⚠️ Avisa, não impede. Ao escolher ele, um aviso amarelo explica que ele saiu e ainda não voltou; ao tocar em Iniciar carga, a tela pergunta uma vez ("carregar assim mesmo?"). Confirmou, carrega normal — a carga fica pronta esperando ele chegar.
🔁 Vale nos dois caminhos: a "Nova Carga" (escolhendo o motorista na lista) e o ▶ do caminhão da escala, que nem passava pela lista. E vale nas duas telas: o app da Expedição no tablet e o "Carregar caminhão" aqui no sistema.
🟢 O "✓ Voltou" continua igual — é ele que tira o motorista da estrada na tela de todo mundo. O aviso serve justamente pra lembrar de tocar nele quando o caminhão chegar de verdade.
Só a tela — não precisa do Luan. Ficou um teste automático com as regras (tests/motorista-em-viagem.test.mjs).
📌 Comprou e o material ainda vai chegar? O Lançamento de Insumos ganhou o "Deixar pendente". É o desenho dos sistemas grandes (Bling, Omie, Odoo): na hora da compra você registra o pedido — nota, fornecedor, itens — e ele fica numa caixa amarela "Aguardando baixa", SEM entrar no custo do mês e SEM mexer no estoque.
✅ Quando o material chega, é um clique: "Dar baixa". Os itens voltam pra lista da tela pra você conferir (dá pra tirar item e ajustar) e o "Lançar" de sempre grava tudo — aí sim entra no custo do mês (o mês da CHEGADA), soma no estoque do almoxarifado e confere com o total da nota, igual já fazia.
🗓️ A caixa amarela mostra há quantos dias cada pedido espera — passou de 7 dias, o aviso fica amarelo: ou o fornecedor atrasou, ou alguém esqueceu de dar baixa.
🛡️ Sem contar duas vezes: cada lançamento leva o carimbo do pedido que o gerou; se a internet cair no meio da baixa, o sistema percebe e não deixa a mesma compra entrar 2× no custo.
Só a tela — não precisa do Luan (o doc novo cc_pedidos_compra é snapshot genérico). Ficou um teste automático com as 8 regras (tests/pedido-compra-baixa.test.mjs).
📦 ORÇAMENTO EM PALETES. O cliente pede "me manda 2 paletes", e agora o orçamento fala essa língua. No item, além da Quantidade (em caixas), apareceram dois campos: 📦 Paletes e Caixas por palete.
✍️ Como usa: escolheu a caixa, o caixas por palete vem sozinho do cadastro dela (aba Paletização — a DEUSA 01.01, por exemplo, já vem com 750). Aí é só digitar 2 em Paletes que a quantidade vira 1.500 caixas na hora — ou digitar as 1.500 caixas e ver que dá 2 paletes.
🔁 A ordem não importa: se o senhor escrever "2 paletes" antes de escolher a caixa, no momento em que escolher a caixa a quantidade se acerta sozinha. E se digitar a quantidade na mão depois, é ela que vale — o sistema segue o último campo em que o senhor mexeu.
🧾 No documento do cliente sai "1.500" na coluna Qtd e, logo abaixo, "2 paletes" — mais a linha "750 caixas por palete" na descrição. Vale no papel impresso, no PDF, no WhatsApp, no app do vendedor e no link que o cliente abre pra aprovar.
🧮 A conta arredonda pra cima: 1.600 caixas de 750 são 3 paletes (o último vai com 100) — porque meio palete também ocupa o lugar de um inteiro no caminhão. A tela avisa quando o último vai parcial.
✋ Caixa que ainda não tem paletização cadastrada: dá pra digitar o "caixas por palete" na mão só pra esse orçamento. E se ninguém disser esse número, o orçamento simplesmente não fala em palete — em vez de chutar um número de frete que não existe.
Nada mudou no preço nem no peso: quem manda continua sendo a quantidade em CAIXAS. Orçamento antigo continua saindo igualzinho ao que já saiu.
📝 A ocorrência da expedição é SÓ REGISTRO — não conta como perda. Como o senhor decidiu: a caixa foi produzida boa e se estragou na doca, no caminhão ou na empilhadeira — não é perda da produção daquele pedido.
🐛 O que estava errado: mesmo sem estar ligada a nenhuma máquina, a ocorrência entrava na conta do relatório de Perda por Etapa. Se o expedidor lançasse 12 caixas amassadas, viravam 12 de perda lançada naquele pedido — e ainda diminuíam a fatia de "perda de processo", bagunçando os dois números.
✅ Agora ela fica de fora dessa conta, e continua aparecendo normal onde ela vale: na tela de Ocorrências e na Vida da Caixa, dentro da estação 🚚 Expedição.
As ocorrências de máquina (chapa trincada, descolando etc.) continuam contando como perda, exatamente como antes — nada mudou pra elas.
⚠️ BOTÃO DE OCORRÊNCIA NO APP DA EXPEDIÇÃO. O expedidor agora tem o mesmo botão que o operador da cartonagem tem — mas com os problemas da doca, não os da chapa. Fica nas duas telas de carregamento (a normal e a do plano de carga), logo abaixo do botão de bipar.
📋 O que ele pode escolher: 📦 avaria no palete/caixa (amassada, torta, rasgada, molhada, suja) · 🏷️ etiqueta (errada, ilegível, palete sem etiqueta) · 🔢 quantidade (palete com menos caixa, contagem não fecha) · 🚛 carregamento (não coube, caminhão sujo/furado, avaria da empilhadeira). Mais quantas caixas foram afetadas, o que aconteceu e até 3 fotos.
✅ Não trava nada (como o senhor pediu): ele registra e continua carregando. Não pausa, não tira palete da carga, não impede fechar. Diferente do app do operador, que pausa o pedido.
📦 Vai pra Vida da Caixa — se ele estiver carregando aquela caixa. A tela pergunta de qual palete é o problema (já vem marcado o último que ele bipou), e é isso que amarra a ocorrência no pedido certo. Lá na Vida da Caixa ela aparece dentro da estação 🚚 Expedição, junto do caminhão e de quem carregou — e não no meio das ocorrências de máquina.
🏭 Na tela de Ocorrências do PCP ela entra sozinha, junto com as outras, só que marcada como 🚚 Expedição e mostrando o caminhão no lugar da máquina.
📶 Sem internet não perde. A ocorrência é guardada no aparelho na hora e sobe sozinha quando a conexão volta — o app avisa qual dos dois aconteceu.
Se ele registrar sem ter bipado nenhum palete, a ocorrência vale pro PCP mas não entra na Vida da Caixa — sem palete não dá pra saber de qual pedido é, e chutar seria pior.
CARREGAMENTO AO VIVO. Na tela Carregar Caminhão, lá em cima, agora aparece quais caminhões estão sendo carregados neste momento e QUEM está carregando cada um. Se tiver 4 expedidores com o app aberto bipando palete, os 4 aparecem: nome da pessoa, placa do caminhão, motorista, quantos paletes já entraram e há quanto tempo foi o último bip.
🔎 O que estava faltando: o painel só enxergava quem carregava pelo Plano de Carga. Quem carrega pela escala ou avulso — que é a maioria — ficava invisível, mesmo com o app bipando normal. Agora os dois caminhos aparecem no mesmo lugar.
📊 O placar de paletes voltou. No carregamento por plano ele mostrava sempre em branco; agora mostra quantos de quantos (ex.: 7/12), com a barrinha de progresso — e conta igualzinho ao que o empilhadeirista vê no app dele.
🗓️ Card do mês. Os cards de cima passaram a ser hoje · esta semana · este mês (era só hoje e semana).
✅ Concluir é quando sai o romaneio. Carga fechada ainda não é carga concluída — sem o romaneio o motorista sai sem papel e o pedido fica parado no faturamento. Então cada carga fechada hoje aparece em uma de três cores: 🔵 carregando · 🟠 fechada, falta o romaneio (com o botão pra imprimir ali mesmo, e dizendo de qual cliente falta) · 🟢 concluído.
🔔 Avisa quando concluir. Assim que o romaneio de todos os clientes daquela carga sai — pelo sistema ou pelo celular do expedidor — aparece o aviso "Carregamento concluído" com o caminhão. Avisa uma vez só, e a primeira vez que você abre o sistema não despeja notícia velha.
Nada novo é gravado e nada precisa ser apertado no servidor: tudo sai do que o app da Expedição já manda. A tela se atualiza sozinha a cada 15 segundos.
🔐 "Editar pedido" e "Mudar status do pedido" agora valem de verdade. Eram as duas últimas chavinhas da tela 🔐 Acessos que ninguém no sistema olhava — você ligava e desligava, ficava salvo, e não mudava nada. Qualquer perfil editava e trocava status, até quem só tem permissão de visualizar.
✅ O que muda na tela: pra quem o perfil não deixa, o botão Editar some das quatro telas onde ele aparece, e o seletor de status fica travado, com a explicação ao passar o mouse.
👥 Quem continua fazendo tudo: admin e pcp — o dia a dia não muda. Quem passa a não poder: visualizador, financeiro, vendedor, desenvolvimento e RH.
➕ Criar pedido novo continua separado. É o mesmo botão Salvar que cria e que edita, então tomei o cuidado de a trava valer só na edição — quem pode criar pedido continua criando.
🎯 Pra liberar (ou tirar) de UMA pessoa só, sem valer pro perfil inteiro, é em 🔐 Acessos, no ajuste por pessoa. O que você marcar lá sempre ganha desta configuração de fábrica.
Fecha a família: era a mesma coisa que a permissão de excluir, consertada na v2.37.446.
↩️ Desistir na pergunta do motivo agora cancela mesmo a exclusão. Na versão passada, quando o sistema perguntava "por que está excluindo?", apertar Esc ou Cancelar não parava nada: o pedido era excluído do mesmo jeito. Dava pra recuperar na 🗑️ Lixeira, mas o susto era de graça.
✅ Agora são três respostas diferentes:
• Esc ou Cancelar → desiste, o pedido continua na carteira e a janela dele fica aberta;
• OK sem escrever nada → exclui sem motivo (continua sendo opcional);
• OK com o motivo escrito → exclui e guarda a explicação.
💬 E a pergunta passou a avisar isso — agora ela diz "Esc cancela a exclusão", pra ninguém precisar adivinhar.
Ajuste do pacote "fechar as porteiras", a seu pedido.
🔒 Caixa que está em algum pedido não pode mais ser excluída. Até agora dava: o sistema perguntava "excluir esta caixa?" e apagava, mesmo com pedidos usando ela. Os pedidos ficavam órfãos — sumia o peso, a paletização, a tinta e a referência do orçamento — e o pior é que o pedido continuava na carteira como se estivesse tudo certo, então ninguém percebia até precisar de um desses números.
📋 Agora o sistema mostra quais pedidos usam a caixa (cliente, data de entrega e situação) e explica o que fazer: trocar a caixa desses pedidos primeiro, ou excluir os pedidos. Depois é só excluir de novo.
🎯 Vale nas três telas — Caixas, e as duas de Micro / Cartão.
⚖️ Na dúvida, ele barra. A trava reconhece o pedido pelo vínculo da caixa e, em pedido antigo sem vínculo, pelo código dentro do mesmo cliente — nunca de um cliente pro outro, que é o erro que já misturou pedido de empresa diferente aqui.
Passo 5 de 5 do pacote "fechar as porteiras". Mesma trava que o cliente e a chapa já tinham.
🔄 O sistema agora avisa quando o pedido pode voltar sozinho. Aquele caso de "eu excluí e no dia seguinte ele estava lá de novo" nunca foi defeito: se o pedido veio do relatório do Sectra e a linha dele vier de novo na próxima importação, o sistema traz ele de volta de propósito — é a rede de segurança pra quem excluiu sem querer.
💡 O que faltava era te contar isso na hora certa. Agora, ao excluir um pedido que veio do Sectra, a pergunta traz uma linha a mais: "Se a linha dele ainda vier na próxima importação, ele VOLTA sozinho pra carteira." Assim você já sabe se precisa tirar a linha do relatório também.
✋ Pedido que você criou na mão não mostra esse aviso — esse não volta.
Passo 4 de 5 do pacote "fechar as porteiras". É só um texto a mais no aviso — nada mudou no funcionamento.
✍️ Agora fica registrado QUEM apagou o pedido — e por quê. Antes, o sistema tinha até onde guardar o nome de quem excluiu, mas nunca mandava: a ficha do banco ficava vazia pra sempre, e o único lugar com o nome era a cópia da 🗑️ Lixeira, que some depois de 60 dias. Depois disso, ninguém mais sabia quem tinha sido.
💬 Ao excluir, o sistema pergunta o motivo. É opcional — se você não quiser escrever, é só apertar OK que a exclusão acontece igual. Se escrever, o motivo aparece no cartão da Lixeira e fica gravado dentro do pedido: se alguém restaurar depois, a explicação volta junto, na Vida da caixa.
📋 Arquivar lançamento de produção também guarda a pessoa. Antes o sistema anotava sempre "pcp-editor", que não é ninguém — dava pra ver que alguém arquivou, mas nunca quem.
Passo 3 de 5 do pacote "fechar as porteiras". Nada muda no que você já faz — só passa a ficar registrado.
🗑️ Excluir por dentro do pedido agora manda pra Lixeira também. Existiam dois botões de excluir e eles faziam coisas diferentes: o ✕ da lista guardava uma cópia na 🗑️ Lixeira (dá pra restaurar por 60 dias), mas o botão Excluir de dentro do pedido apagava de vez — sem cópia, sem volta. Quem apagasse por ali só recuperava pedindo o backup do banco pro Luan.
🤫 E nada avisava. A perguntinha daquele botão só dizia "Excluir pedido de Fulano?" — não falava em Lixeira, então não dava nem pra desconfiar que ali era diferente.
✅ Agora os dois botões são o MESMO caminho. Excluir por dentro do pedido faz exatamente o que o ✕ da lista faz: a mesma pergunta (que cita a Lixeira e os 60 dias), a mesma cópia guardada, as mesmas travas.
🔒 Se você clicar em "cancelar", o pedido continua aberto na sua frente — não fecha a janela nem perde o que você estava vendo. Igual pra quando o sistema barra a exclusão (pedido já carregado no caminhão, ou perfil sem permissão).
Passo 2 de 5 do pacote "fechar as porteiras". Nada muda pra quem já usava o ✕ da lista.
🔐
Agora o sistema respeita quem pode e quem não pode excluir pedido. Na tela 🔐 Acessos sempre existiu a chavinha
"Excluir pedido" por perfil — você ligava e desligava, e ela ficava salva. Só que
nenhuma parte do sistema olhava pra ela: o botãozinho ✕ do pedido aparecia pra todo mundo, até pra quem só tem permissão de
visualizar, e apagava do mesmo jeito.
✅
O que muda na tela: pra quem o perfil
não deixa excluir, o ✕ some do card de produção, some da tabela do Relatório e some do botão Excluir de dentro do pedido. E se a pessoa tentar por outro caminho, o sistema barra e explica: "Seu perfil não pode excluir pedidos".
👤
Pra quem PODE, nada muda — continua tudo igual, inclusive a 🗑️ Lixeira e a trava de pedido que já foi carregado.
👥
Quem continua excluindo: admin e
pcp — ou seja, quem apaga pedido no dia a dia
não perde nada. Quem passa a não poder: visualizador, financeiro, vendedor, desenvolvimento e RH.
🎯
Se você quiser liberar (ou tirar) de UMA pessoa só — sem valer pro perfil inteiro —, dá pra fazer em
🔐 Acessos, no ajuste por pessoa. O que você marcar lá
sempre ganha desta configuração de fábrica.
Passo 1 de 5 do pacote "fechar as porteiras" — as proteções contra apagar coisa sem querer.
🗑️ Excluir chapa agora apaga de verdade. O botão só tirava a chapa da tela — no servidor ela continuava viva e voltava no próximo carregamento. Era isso que acontecia com as chapas repetidas: você apagava, dava F5, e lá estavam elas de novo. Agora o excluir apaga no banco, igual já acontece com as cores, os clientes e as caixas.
📦 Chapa que alguma caixa usa não sai sem avisar: o sistema mostra a lista das caixas (código e cliente) e segura a exclusão. Você troca a chapa dessas caixas primeiro e depois exclui — assim nenhuma caixa fica apontando pra uma chapa que não existe mais. (Das 191 caixas cadastradas, 189 têm chapa ligada.)
🛡️ Se o servidor não responder, a chapa NÃO some da tela — ela avisa e continua ali. Sumir e voltar depois é pior do que não sumir.
Só a tela — não precisa do Luan (a rota de exclusão já existia no servidor). Ficou um teste automático com as 3 regras.
🎨 A tela do Almoxarifado da Cartonagem mostra só a tinta que a fábrica usa. A lista tinha 67 tintas porque a tabela de preço inteira da SILRESIN entrou no cadastro — e a fábrica trabalha com umas 18 cores. Agora vem curta, com a caixinha "só o que a fábrica usa" já ligada (é só desmarcar pra ver tudo de novo).
📋 Fica na tela o que é da casa: a cor ligada ao Cadastro de Cores e a que já teve entrada alguma vez — mesmo estando zerada hoje. É por isso que o AZUL DH 007, que recebeu 40 kg e já acabou, continua aparecendo: quem olhasse só o saldo esconderia justo a tinta que gira.
📦 Tinta com estoque ou com mínimo cadastrado nunca some, mesmo sem cor ligada — o BASE PRETO (38 kg) e o AZUL 01 (20 kg) não têm vínculo, e são 58 kg de tinta de verdade.
🔎 Na busca, a lista volta a ser inteira. Quem digita um nome está procurando aquilo — sumir com o resultado seria o pior tipo de defeito, o calado.
🗑️ Nada foi apagado — só escondido. O mesmo cadastro é o estoque do app de celular do almoxarife, e item apagado aqui sumiria da mão dele na hora de comprar.
Só a tela — não precisa do Luan. Ficou um teste automático com as 4 regras, pra nenhuma tinta da casa sumir por engano.
⚠️ Aquele aviso "não consegui ler as caixas da API" agora diz POR QUE. Ele aparecia sem explicar nada, e o motivo ia só pro console do navegador — que ninguém abre. Sem o motivo, cada vez que aparecia virava uma investigação do zero. Agora o aviso mostra o motivo junto (e, se for recusa do servidor, o número do erro).
🔁 E um soluço de internet não bloqueia mais o salvar. Antes, UMA falha de leitura já travava o salvar até você recarregar a página. Agora o sistema tenta de novo em 3 segundos antes de travar. Se a segunda tentativa der certo, você nem vê o aviso.
🔒 A trava em si continua: se falhar de verdade, o salvar segue bloqueado — é ela que impede o sistema de gravar cadastro em cima de uma leitura que não deu certo. O que mudou é ela não disparar no primeiro tropeço.
🕵️ Investigação, com honestidade: medi a rota de fora e ela respondeu certo (as 191 caixas em 1 segundo). Não achei a causa raiz do seu caso — mas achei um forte suspeito, que é do servidor: a API pede pra não guardar os dados em cache, e o servidor está mandando guardar por 10 minutos, por cima da ordem da API. Isso é o Luan que resolve (configuração do nginx) e vale pra todos os cadastros, não só as caixas.
Se o aviso voltar, agora ele vem com o motivo escrito — me manda o print que aí eu sei onde olhar. Só a tela; a parte do cache precisa do Luan.
🚫 O sistema parou de baixar o arquivo de backup sozinho. Aquela janela "Salvar Como: mtx_backup_auto_…json" que abria no meio do trabalho — e até de madrugada — não abre mais. Ela vinha de dois lugares: o backup do fim do dia e um "auto-download silencioso" a cada 30 alterações, que era o que mais atrapalhava.
☁️ O backup na nuvem continua igual, todo dia, sem aparecer pra ninguém. O que saiu foi só o arquivo caindo na pasta Downloads.
💾 Pra ter o arquivo na mão, o caminho é o de sempre: Backup ▸ Baixar backup. Aí sim ele pergunta onde salvar, porque você pediu.
🧹 A caixinha "Auto-download silencioso" foi tirada da tela de Backup — ela não fazia mais nada e só ia confundir.
Só a tela — não precisa do Luan. Lembrando que este .json é cópia de conforto: o backup que vale é o dump do banco, que roda todo dia 12:30 no Mac.
🧭 As telas da Expedição voltaram a aparecer no menu do noel. Elas nunca sumiram de verdade — estavam num grupo fechado da barra da esquerda, e grupo fechado não mostra os itens.
🔎 O que era: na versão anterior o menu passou a abrir sozinho "o primeiro grupo que tem telas". Só que o perfil 🧩 Expedição tem 2 telas em 📋 Cadastros (Motoristas e Expedidores), e Cadastros vem antes de 🚛 Expedição na ordem do menu. Então ele abria Cadastros, com aqueles 2 itens, e as 6 telas de expedição ficavam escondidas no grupo de baixo.
✅ Agora ele abre o grupo da tela em que você está — que, ao entrar, é a primeira tela do seu perfil. O noel entra em Entregas e o grupo 🚛 Expedição já vem aberto. Admin e PCP não mudam nada: continuam abrindo em 🏭 Produção.
🛡️ Ficou um teste automático que confere a ordem real dos módulos e acusa se alguém reordenar o menu e trouxer o problema de volta.
Terceira vez que este perfil aparece numa correção de menu (424, 433 e agora). Só a tela — não precisa do Luan.
🔒 A tela de Ponto agora pede login — antes qualquer pessoa com o endereço abria e via o ponto de todo mundo. O painel_ponto.html (o espelho gerencial de bater ponto, importar o arquivo do relógio e ver salário/custo por funcionário) não tinha senha nenhuma: só o link. A partir de agora ele pede o MESMO usuário e senha do sistema — nada de PIN novo.
🕵️ Achado no caminho: além da tela em si, o servidor deixava os TRÊS dados de dentro dela passarem sem checar permissão nenhuma (as batidas, o cadastro de funcionário e o salário) — bastava ter o token da fábrica, que é o mesmo em todo aparelho. Agora os três também exigem a permissão de "Ponto" (ou de "Fichas"/"Fixos & Funcionários", cada um o que já era dele).
🧹 No caminho, um buraco irmão do que fechamos na v2.37.434: as telas de Fichas/Escala/Ponto nunca tinham essa permissão anotada de verdade pra Admin nem pro Financeiro — só apareciam pra eles na hora de abrir a tela. Sem corrigir isso, travar o servidor agora derrubaria você mesmo (e o Financeiro) da própria tela de Ponto.
🧵 Os outros apps da fábrica não mudam em nada — só esta tela, que nem estava em uso por mais ninguém, ganhou login.
🔧 Precisa do Luan: a porta da tela (o login) já vale assim que ela subir, sozinha, pelo cronjob. A trava de dentro do servidor só entra em vigor depois que ele rodar a atualização do banco (npm run db:migrate) e reiniciar a API (pm2 restart) — até lá, continua exatamente como hoje, sem recusa nova nenhuma.
Etapa 5b do trabalho de permissões. Testado com Postgres e API reais (Docker) contra os 4 perfis que usam essas telas.
🤝 A comissão já paga não ia sumir da tela — mas quase. Na versão anterior, a lista de comissões pagas passou a exigir a permissão da tela de Vendedores, que só o Admin tem. O problema é que quem escreve nessa lista é a baixa no Financeiro — e esse caminho não passa pela tela de Vendedores. Efeito: dar baixa numa conta de comissão baixava a conta, mas não marcava a comissão como paga. Ela ficaria eternamente como "no financeiro" no relatório e "não paga" no app do vendedor, sem nenhum aviso — com risco de pagar a mesma comissão duas vezes.
✅ Agora a lista está ligada à permissão de Lançamentos, que o Admin, o PCP e o Financeiro têm — e o Visualizador continua fora. Ninguém que já conseguia mexer em comissão perdeu acesso.
🛡️ E ficou um teste automático pra isso não voltar: ele confere, a cada mudança, que toda lista protegida continua alcançável por quem precisa escrever nela — não só por quem abre a tela. Esse era o furo dos dois últimos ajustes de permissão.
Achado conferindo a versão anterior antes de subir. Precisa do Luan (reiniciar o servidor) junto com as versões 433 a 438.
🔐 O App do Vendedor agora se identifica direto pro servidor, com login e senha — não é mais só o PIN conferido no celular dele. Por causa disso, os dados de Orçamento (inclusive as Solicitações) e o relatório de Comissão deixam de ficar abertos pra qualquer aparelho que tenha o token da fábrica: agora só entra quem o servidor reconhece.
🕵️ Achado no caminho: a senha (PIN) do vendedor estava indo em TEXTO PURO em toda consulta ao cadastro — qualquer um com o token conseguia ler a senha de todos os vendedores. Corrigido: a senha vira um código (hash) no banco e nunca mais é devolvida — nem pro próprio sistema. Quem edita o cadastro de um vendedor sem trocar a senha dele: deixe o campo da senha em branco (ele mantém a senha atual).
🧵 Os outros apps da fábrica não mudam em nada. Só o App do Vendedor ganhou esse login novo — operador, expedição, motorista, qualidade, compras e almoxarifado continuam exatamente como estavam.
🔧 Precisa do Luan: essa novidade só entra em vigor depois que ele rodar a atualização do banco (npm run db:migrate) e reiniciar a API (pm2 restart). Até lá — e mesmo se o restart vier antes da atualização do banco por engano — o App do Vendedor continua funcionando exatamente como hoje, sem travar ninguém.
Etapa 5a do trabalho de permissões. Testado com 28 casos automáticos contra um banco de teste de verdade (Postgres via Docker), incluindo a API real respondendo às chamadas.
🧯 Agora TODOS os apps recebem conserto de arquivo compartilhado. Ontem só o da Qualidade foi arrumado; hoje foram os outros 19 apps (operador, expedição, vendedor, motorista, manutenção, compras, almoxarifados, onduladeira, escala, encarregado, desenvolvimento, bobinas, portal do cliente e os demais) — 58 arquivos que eram guardados no aparelho e nunca mais trocados.
⚠️ Por que isso importava: entre esses arquivos estão o do fim de turno (app do operador), o do romaneio (Expedição) e o da nota de orçamento (vendedor). Conserto feito neles podia não chegar no celular de quem usa — sem erro, sem aviso, só continuava com o defeito antigo.
Daqui pra frente o carimbo de versão se atualiza sozinho a cada publicação. Nenhuma tela mudou de aparência.
🧯 O app da Qualidade não recebia conserto de arquivo compartilhado. Descoberto ao subir o conserto da impressão do laudo: o app carregava 4 arquivos sem o carimbo de versão — e arquivo sem carimbo o celular guarda e não troca mais. Ou seja, o conserto de ontem podia simplesmente não chegar nesse app. Carimbados agora (inclusive o do laudo), e daqui pra frente o carimbo se atualiza sozinho a cada versão.
Os outros apps têm o mesmo detalhe em 3 arquivos compartilhados — vou tratar em seguida, um de cada vez.
🖨️ As fotos do laudo saíam EM BRANCO no papel. No Windows, o laudo imprimia com os três quadros do Registro fotográfico dos testes vazios — na tela apareciam certinho. Motivo: a janela de impressão abria e mandava imprimir 3 décimos de segundo depois, sem esperar as fotos carregarem; no Mac dava tempo, no Windows não. Agora o laudo espera cada foto ficar pronta antes de mandar pra impressora (e, se alguma não carregar, imprime mesmo assim depois de 6 segundos — nunca trava). Vale no sistema e no app da Qualidade.
📸 Foto do caminhão com mais qualidade. A pedido: a foto do carregamento passou de 1024 para 1600 pixels e de qualidade média para alta — dá pra ler a placa e ver como a carga foi amarrada. Ficou em torno de 3× maior (algo entre 300 e 500 KB); conferido no servidor que sobe e volta sem problema, e ela continua guardada fora da lista de cargas, então não pesa no dia a dia de ninguém.
Fotos antigas continuam como estão. Não precisa do Luan.
📸 A foto do caminhão não abria no sistema. A foto era tirada e salva certinho (conferido no servidor: a carga de 18/08 tinha a foto de 122 KB guardada), mas ao clicar em "Ver foto do caminhão" a tela dizia "não deu pra buscar a foto — confira a conexão", mesmo com a internet boa. Motivo: o app da Expedição e o sistema falam com o servidor por caminhos diferentes, e a busca da foto usava o caminho do app. Agora usa o do sistema. Nenhuma foto se perdeu — as que já foram tiradas aparecem normalmente a partir desta versão.
Só a tela de ver a foto. Tirar a foto e fechar a carga continuavam funcionando.
🔐 Agora o SERVIDOR recusa de verdade quem não tem permissão — não é mais só a tela escondendo o botão. A versão anterior só tinha começado a ANOTAR, no banco, o que cada perfil (Admin, PCP, Financeiro...) pode ver. A partir de agora, nas telas de DINHEIRO e de GENTE (Contas & Previsão, Conciliação, Lançamentos, Fixos & Funcionários, Faturamento, RH, gerenciar usuários, backup), o pedido chega no servidor e ele CONFERE — quem não tem a permissão recebe uma recusa, mesmo sabendo o endereço da informação por fora da tela.
🚧 Os painéis Conciliação, DRE e RH (os separados, sem login próprio) vão parar de abrir esses dados. Você confirmou que não usa mais esses três painéis soltos — a partir de agora eles mostram recusa em vez do extrato/DRE/fichas. As telas de Conciliação, Contas, Fixos, Lançamentos e Faturamento de DENTRO do sistema continuam normais pra quem sempre teve acesso.
🧵 Os outros apps da fábrica (operador, expedição, motorista, vendedor, qualidade...) não mudam em nada — só as telas de dinheiro/gente é que passaram a exigir permissão; o resto continua exatamente igual.
🔧 Precisa do Luan: essa trava só entra em vigor depois que ele rodar a atualização do banco (npm run db:migrate) e reiniciar a API (pm2 restart). Até lá — e mesmo se o restart vier antes da atualização do banco por engano — continua tudo funcionando exatamente como hoje, sem recusa nenhuma nova.
Etapa 4 de um trabalho em 4 partes (a última). Testado com 21 casos automáticos contra um banco de teste de verdade (Postgres via Docker), incluindo a API real respondendo às chamadas.
🔒
A tela não troca mais de usuário sozinha. Aconteceu hoje: o dono estava no admin, tinha testado o acesso da Expedição, veio a atualização automática — e a janela do admin
entrou como o usuário da Expedição sozinha.
🔎
Por que: quem está logado fica guardado no navegador, e é
um só por navegador — não um por aba. Entrar com outro usuário em qualquer janela troca a sessão de todas. A janela antiga não percebe, porque já está desenhada. No recarregamento seguinte ela restaura o que está guardado e entra como a outra pessoa,
calada.
✅
Agora cada aba lembra quem entrou NELA. Se na volta o usuário guardado for outro, a aba
não entra sozinha: mostra a tela de login com o aviso "entraram com outro usuário neste navegador".
👍
Pra quem só trabalha, nada muda. Abrir o sistema, atualizar a página e voltar depois continua entrando direto — a tela de login só aparece quando a pessoa realmente mudou.
⚠️
Isto tapa um buraco, não fecha a porta. Uma aba NOVA continua restaurando a sessão guardada, então
computador compartilhado ainda é risco: quem abrir o sistema depois de você herda o seu acesso, sem senha. Quem fecha isso de verdade é o servidor conferir o crachá — já está pronto no sistema desde 15/08 e depende do Luan rodar
uma vez:
npm run db:migrate e
pm2 restart all. Enquanto isso não roda, o servidor responde "não sei quem é você" e quem decide é o navegador.
Dica enquanto isso: pra testar outro usuário, use uma janela anônima — ela tem sessão própria e não encosta na sua. Testado nos 3 casos: pessoa trocou (barra), mesma pessoa (entra), aba nova (entra).
🧭 O menu vinha em branco pra quem não trabalha na Produção. O usuário da Expedição entrava e a barra da esquerda aparecia vazia — com as telas dele liberadas no perfil, mas nenhuma na tela.
🔎 O que era: o menu decide qual grupo abrir uma vez só, quando a página carrega — e nessa hora ainda não existe usuário logado, então ele sempre abria o grupo 🏭 Produção. Pra quem é do PCP isso nunca deu problema (Produção é dele). Já um perfil só de Expedição não tem nenhuma tela em Produção: o grupo fica vazio e escondido, aí nenhum grupo ficava aberto — e grupo fechado não mostra os itens. Menu em branco.
✅ Agora, se nenhum grupo com telas estiver aberto, o sistema abre o primeiro que tem. A conta passou pro lugar que roda a cada login, e não só no carregamento da página.
🖐️ E não briga com você: depois que a pessoa clica num grupo pra abrir ou fechar, o sistema não abre mais nada sozinho.
Quem já via o menu não muda nada — o PCP e o admin continuam abrindo em Produção. Testado com os dois perfis. Só a tela, não precisa do Luan.
🧱 Começou o alicerce de acessos do sistema — esta versão ainda NÃO tranca nada. É só a base: o servidor passou a ter, no próprio banco, uma lista do que cada perfil (Admin, PCP, Financeiro...) pode ver e fazer — hoje quem manda continua sendo a tela, igual sempre foi. Isso prepara o terreno pra próxima etapa, que aí sim vai reforçar a trava no servidor.
📝 Passou a ficar registrado quem entrou, quem saiu e quem tentou fazer algo que não podia. O sistema já tinha uma "caderneta" pronta pra isso (existia desde sempre, só nunca tinha sido usada) — agora toda vez que alguém entra, sai, ou tenta uma ação de administrar acesso sem ser o admin principal, fica uma linha gravada: quem foi, quando, e o que aconteceu. Isso não aparece em tela nenhuma ainda — é registro pra investigar se um dia precisar.
🔧 Precisa do Luan: essa versão só entra em vigor depois que ele rodar a atualização do banco (npm run db:migrate) e reiniciar a API (pm2 restart). Até lá, e mesmo se o restart vier antes da atualização do banco por engano, o sistema continua funcionando exatamente como hoje — login, telas e tudo mais — sem trava nenhuma nova e sem erro pra ninguém.
Etapa 3 de um trabalho em 4 partes. Testado com 34 casos automáticos + um banco de teste de verdade. Não muda nada do que você vê ou pode fazer hoje. ⚠️ Duas mudanças diferentes acabaram saindo com o mesmo número (v2.37.433) por sessões separadas — ficam as duas entradas, sem apagar nenhuma.
🖥️ O menu de cima não pisca mais antes do menu lateral aparecer. Ao abrir o sistema, por um instante aparecia o menu ANTIGO (a barra horizontal no topo) e só depois pulava pro menu LATERAL que você já usa hoje. Motivo: a página nasce mostrando o menu antigo (que continua ali, escondido só depois por um JS que termina de rodar quando o arquivo inteiro carrega) — e o arquivo do sistema é grande, então numa conexão mais lenta dá tempo do menu antigo aparecer antes da troca. Agora a página já nasce com o menu antigo escondido e só o LATERAL é mostrado, sem pulo nenhum.
🛟 Com uma rede de segurança: se por algum motivo o menu lateral não conseguir montar (erro no meio do carregamento, conexão muito lenta), depois de uns 3 segundos o menu antigo volta a aparecer sozinho — pra nunca ficar sem menu nenhum na tela.
Não muda nada de como o sistema funciona, só o instante em que o menu aparece. Só a tela — não precisa do Luan.
🔒 Trocar de usuário no mesmo computador não vaza mais o dado do anterior. Quando alguém saía e outra pessoa entrava no mesmo navegador (ex.: você sai, a Expedição entra), o Dashboard com pedidos, valores e faturamento aparecia na tela por 2 a 3 segundos antes do login decidir quem é a nova pessoa — o dado ficava guardado no aparelho, pronto pra aparecer de novo pro próximo. Quatro consertos juntos:
🧹 Sair e entrar com outro usuário agora limpa o computador. O botão "Sair" só apagava a sessão — nunca os pedidos, clientes e contas guardados no aparelho. Agora ele limpa tudo e recarrega a tela. E se você sair sem clicar em "Sair" (só fechar o navegador) e OUTRA pessoa entrar depois no mesmo aparelho, o sistema percebe que o dono mudou, limpa na hora e recarrega — sem precisar de ninguém clicar em nada.
⏳ Nada é desenhado antes do login decidir quem é você. Antes o sistema montava o Dashboard (com os números) assim que a página abria, e só depois perguntava quem estava entrando — a tela de login subia por cima, mas o de baixo já estava desenhado. Agora o Dashboard só é montado depois que o login termina.
🚫 Perfil que o sistema não reconhece deixou de "ver tudo por engano". Um perfil novo criado por você (ex.: 🧩 Expedição) que ainda não tinha chegado num aparelho caía, por 2-3 segundos, num modo que mostrava Dashboard, Relatório e PCP — as telas com dinheiro e carteira. Agora, nesse caso raro, o sistema não mostra tela confidencial nenhuma e avisa: "Não deu pra confirmar suas permissões agora. Recarregue a página."
Achado numa revisão de segurança (18/08/2026). Testado com 17 casos automáticos. Só a tela — não precisa do Luan.
📄 Fechou o caminhão, o sistema já cobra o romaneio. Assim que a expedição finaliza o carregamento, aparece na mesma tela um aviso "falta imprimir o romaneio", com um botão por cliente da carga — do lado do botão do WhatsApp, que continua igual.
🚚 Por que isso importa: o romaneio é o papel que vai com o motorista — e é ele que libera o pedido pro faturamento. Carga fechada sem romaneio é caminhão na estrada sem documento e pedido parado, sem ninguém saber.
🔔 E se sair da tela, o aviso volta. Enquanto o romaneio daquela carga não sair, uma caixa no meio da tela cobra de novo. Quem fechar em "Agora não" é lembrado outra vez em 10 minutos.
✅ Some sozinho quando o papel sai — não importa por onde: aqui pelo sistema ou pelo celular do expedidor, no app da Expedição. Nada pra marcar na mão.
🤐 E se a internet cair, ele fica quieto. Sem conseguir perguntar ao servidor quais romaneios já saíram, o aviso não aparece — mandar imprimir de novo daria dois números pra mesma entrega, e isso é pior que não avisar.
👀 Só quem trabalha na expedição vê. Quem não tem a tela de carregar caminhão não é incomodado. Carga de mais de 3 dias também não vira alarme.
Só a tela — não precisa do Luan. Testado com 6 situações, incluindo servidor fora do ar e romaneio já emitido pelo celular.
⏱ Coladeira e Grampeadeira: depois das 16:48 o app não abandonava mais ninguém. Essas duas têm turno único (07:00 às 16:48, intervalo 11:00–12:00). Quem entrava depois do fim do turno ficava sem relógio nenhum: o app não avisava, não perguntava a quantidade e nunca fechava o apontamento — o cartão passava a noite no Mural marcando "RODANDO", e a produção do dia seguinte entrava no dia de ontem.
🌙 Agora ali é HORA EXTRA, e hora extra também tem relógio: 2 horas contadas do login — a mesma janela que o app já dá pra quem responde "SIM, vou continuar". Entrou 17:30? Ele confere a produção às 19:30, e se você responder SIM ganha mais 2 h.
🗣️ E a tela parou de mentir. Antes ela diria "seu turno acaba às 19:30" — turno nenhum acaba ali. Agora aparece "⏱ HORA EXTRA · o app confere a produção às 19:30".
🛡️ Quem entra faltando pouco pro fim também não é mais fechado no login. Entrou 16:30 na Coladeira? Vira hora extra até 18:30, em vez da pergunta na cara dele e do fechamento às 16:53.
🔒 A Slotter e a Corte e Vinco não mudaram em nada — elas têm 2º turno e quem entra no fim do turno da noite continua fechando 00:41, como antes. O teste confere isso em 9 horários diferentes.
Os horários das máquinas já estavam certos na configuração — não mexi em nada lá. Só o app do operador. Não precisa do Luan. 41 casos no teste.
⚖️ O romaneio que vai com o caminhão estava saindo com PESO ZERO. O papel que o motorista leva mostrava a quantidade de caixas certinha, mas a coluna de peso vinha 0 kg, a descrição da caixa vinha em branco e a qualidade vinha "—". Em toda carga, desde sempre.
🔎 Por que ninguém viu: não dá erro nenhum. O romaneio imprime bonito, com o cliente, o pedido, o número de paletes e o total de caixas — só as três colunas da caixa é que saem vazias, e isso parece cadastro de caixa incompleto, não defeito do sistema.
🔧 O que era: na hora de montar o papel, o sistema procurava a lista de caixas num lugar onde ela nunca esteve. Como não achava a lista, não achava a caixa — e sem a caixa não tem peso, nem descrição, nem onda/gramatura. Mesma família do defeito que derrubou o menu na v2.37.424.
✅ Medido antes e depois com uma carga de 900 caixas: antes 0 kg, agora 378 kg, com a descrição, a medida e a qualidade no lugar.
Vale pro romaneio impresso pelo sistema e pro PDF que o expedidor emite pelo celular — os dois usam o mesmo papel. Não precisa do Luan.
📡 Tablet com o horário de turno velho — a outra metade da reclamação. O horário de fim de turno só chegava no tablet por um aviso automático que é ligado uma única vez, quando o app abre. Se o servidor demorava nesses primeiros segundos, o aviso não ligava nunca mais — e o aparelho passava a usar a cópia guardada nele, que podia ser de semanas atrás. Por fora parecia tudo normal: o tablet continuava online pro resto.
🔎 Foi o caso do Mirailton, ontem: a Coladeira pergunta às 16:18 e ele recebeu a pergunta às 15:22 — o horário de quando "horas por turno" ainda era 8,8.
✅ Agora o próprio relógio vai buscar o horário, sozinho, no login e de 10 em 10 minutos, sem depender daquele aviso. Mudou o turno no Cronograma? Os tablets pegam em minutos.
🔒 E o horário guardado passou a ter data. Se o servidor não confirmar o horário há mais de 24 horas, o app não encerra o turno de ninguém — fica quieto, como já fazia quando a configuração ainda não tinha chegado. Melhor não fazer nada do que fechar o turno de alguém por um horário que pode ter mudado.
Só o app do operador. Não precisa do Luan. 25 casos no teste, e a busca conferida contra o servidor de verdade.
📥 Agora dá pra conferir o que desceu do caminhão, rolo a rolo. Até aqui o rolo entrava no estoque lá atrás, na conferência da Qualidade (nota + balança) — quem descarregava colava a etiqueta e guardava, sem confirmar nada. Se um rolo da nota não descesse, o sistema seguia achando que ele estava no galpão, e a falta só aparecia quando alguém fosse procurar o rolo pra rodar.
🧾 No app Estoque de Bobinas, aba "📥 Conferir descarga": os rolos aparecem agrupados por nota fiscal, com dono, gramatura, largura e peso. O empilhadeirista bipa cada rolo (ou aperta "✅ desceu") e a linha fica verde. Cada nota mostra "2/3 conferidos", e um número na aba diz quantos ainda faltam.
🪵 Toco não entra na lista — ele não desce de caminhão. Rolo que já saiu pra máquina também não.
🔒 Conferir não mexe no estoque. O rolo continua disponível do mesmo jeito; o que muda é a fábrica saber o que foi visto de verdade. Quando falta rolo, a tela diz o que fazer com todas as letras: "se não desceram do caminhão, isso é cobrança de nota — fale com a Qualidade/Compras". Marcar sozinho que o papel sumiu não é decisão do app.
🤐 E se a internet cair, ela não mente: em vez de mostrar tudo como "não conferido", avisa que não deu pra perguntar — e o contador da aba não inventa número. Bipar duas vezes o mesmo rolo também não gera registro em dobro.
⏰ Quem entra pro 2º turno não é mais fechado no login. O operador do 2º turno bate ponto uns minutos antes da virada — e o app entendia que ele estava terminando o 1º turno. Resultado: a pergunta de fim de turno pulava na cara dele assim que entrava, e o app encerrava o turno dele em seguida.
📋 Aconteceu ontem, 17/08, na Slotter: o Arnaldo entrou 14:33 e o app fechou o turno dele 14:34 — 19 segundos depois. O Fabricio entrou num laço: 5 logins, 3 fechamentos e 3 "hora extra" em 90 segundos.
✅ Agora, quem entra nos 30 minutos finais de um turno recebe o turno SEGUINTE. Entrou 14:33 na Slotter? O turno dele acaba 00:36, não 14:48.
🌙 E onde há buraco entre os turnos, nada mudou. Na Slotter o turno da noite fecha 00:36 e o próximo só abre 05:00 — quem entra ali é o do turno que está acabando mesmo, e continua com o relógio dele (senão o apontamento ficaria aberto a noite inteira). Na Coladeira e na Grampeadeira, que têm 1 turno só, também está tudo igual a antes.
Só o app do operador. Não precisa do Luan. Testado com a configuração de turno real da fábrica (20 casos).
🕐 A barra atrasada agora diz que horas ela DEVIA ter rodado. Quando um pedido não começou, o cronograma empurra ele pra frente — do jeito que tem que ser. Só que aí a barra aparecia num horário esquisito, com o selo ATRASADO, e não dava pra saber de onde aquilo saiu. Foi o caso da TANGARA que você viu às 23:20: o plano dela era 06:56. Agora, passando o mouse na barra, aparece "· previsto 06:56".
🔢 A numeração voltou a começar no 1º. Ela estava começando no 7º — a lista "Ordem de Produção" guardava 6 pedidos que já tinham saído do cronograma, e eles seguravam os números de 1 a 6 pra sempre. Era por isso que a tela mostrava "22º" com 15 pedidos na frente.
📌 E o número parou de mudar no meio do turno. Antes, quando alguém concluía um pedido, todos os de baixo subiam uma casa — o operador perdia a referência com a máquina rodando. Agora o número sai do plano do dia, que é congelado: quem é 5º de manhã continua 5º à tarde, mesmo com gente terminando na frente. Quem entra depois pega o fim da fila, sem mexer em ninguém.
Achados nº 3 e nº 6 da revisão do cronograma. Só a tela. Não precisa do Luan.
🔪 Caixa de chapa, micro ou facão sem máquina agora AVISA — antes de o pedido sumir. Quando uma caixa desses setores não aponta pra nenhuma máquina do cadastro, o pedido dela nasce sem roteiro e cai no caminho antigo: aparece pro operador da Slotter/Coladeira, e quem ia rodar no Cabeçote ou no Facão nunca vê. Não dá erro, não fica vazio — fica no lugar errado, calado. Foi assim que 20.000 chapas prontas ficaram invisíveis pra fábrica em 04/08.
📋 Em Cadastros → Caixas, uma faixa vermelha lista as caixas nessa situação, com o cliente, o setor, o motivo e um botão abrir que já leva pro cadastro pra escolher a máquina.
📐 E na hora de programar, o aviso aparece dentro do modal: "esta caixa é de chapa e não tem máquina nem fechamento escolhidos no cadastro" — no momento em que o PCP ainda pode arrumar.
✅ Caixa de facão que já tem o Facão/Integrada cadastrado se resolve sozinha e não é acusada. E se o cadastro de máquinas ainda não carregou, a tela fica calada em vez de dizer que a máquina não existe.
🔎 Medido hoje: das 184 caixas, só 2 são desses setores — e a de chapa (51900) está sem máquina. É cadastro pra preencher, não conserto de código; o aviso é pra não depender de alguém lembrar.
⚙️ Pedido sem máquina ia pra Slotter sem ninguém saber. Quando o pedido não tinha máquina escolhida, o cronograma desenhava ele na Slotter por conta própria — ocupando a fila dela e empurrando os outros, sem nada na tela dizendo que aquilo foi escolha do sistema, não sua. Hoje são 4 pedidos nessa situação, 2 deles em produção.
📋 Agora o cronograma pergunta ao cadastro da CAIXA primeiro. Se a caixa tem a 1ª máquina definida, é ela que vale — a mesma regra que já dá a máquina ao pedido novo (inclusive "caixa de corte e vinco vai pra Máq. A, nunca a Slotter"). 66 das 183 caixas já têm esse campo preenchido.
⚠️ E quando ninguém definiu, a tela AVISA. O card do pedido mostra "Sem máquina definida — está desenhado na Slotter por padrão". Continua desenhando (nada some), mas você vê que falta escolher — no pedido ou no cadastro da caixa.
🔒 Nada foi mexido nos pedidos. É só leitura pra desenhar a raia. E medido antes de subir: nenhum dos 4 muda de máquina agora — os quatro continuam onde estavam, só que agora com o aviso.
Achado nº 2 da revisão do cronograma. Só a tela. Não precisa do Luan.
✂️ O corte que o operador fez agora APARECE na raia. Quando uma máquina cortava um pedido que não estava programado pra ela, o trabalho não desenhava barra nenhuma — a raia ficava vazia, como se a máquina não tivesse rodado. Foi o que você viu ontem: o Fabricio cortou 5.622 caixas do NACON 04 FRAÇÃO VIGOR no Corte e Vinco, das 05:21 às 07:03, e o cronograma mostrava a raia livre — com um TANGARA que nunca rodou ocupando o lugar.
✅ Agora a barra sai no horário certo, marcada como concluída, com a quantidade e o nome de quem rodou — igualzinha à barra de um corte que estava no plano. O sistema já sabia desse trabalho (guardava a máquina e a quantidade); só faltava desenhar.
📅 Só o que rodou NAQUELE dia. Corte feito em dia anterior continua sem barra hoje — senão o trabalho de ontem apareceria misturado no de hoje. E o cronograma não inventa: registro sem hora de início continua sem barra, do jeito que era.
🔎 De onde veio: revisão do cronograma de 17/08. 51 barras estavam nessa situação no histórico.
Só a tela do cronograma. Não precisa do Luan.
📸 Foto do caminhão carregado, obrigatória pra fechar a carga. No app da Expedição, ao tocar em Finalizar aparece a tela pedindo a foto do caminhão. Sem foto a carga não fecha — o botão só libera depois que ela é tirada. Dá pra tirar até 3 (uma já basta) e apagar a que não ficou boa. Vale nos dois jeitos de fechar: pelo scanner de palete e pelo plano de carga.
👁 No sistema, a foto fica no histórico de cargas. Abrindo a carga pelo 👁 tem o botão "📸 Ver foto do caminhão", com quem tirou e a hora. Carga fechada antes desta versão aparece como "sem foto" — nada foi perdido, é que a foto não existia.
🪶 A foto não pesa no sistema. Ela é reduzida no próprio tablet (fica em torno de 100 KB) e guardada num arquivo separado por carga, buscado só quando você pede pra ver. A lista de cargas, que todos os aparelhos baixam o tempo todo, continua leve igual.
Só o app da Expedição e a tela de histórico. Não precisa do Luan.
🗂️ Mais de uma tela aberta ao mesmo tempo. Pedido do dono: "estou no cadastro de cliente, quero abrir o de caixas, depois ir pro PCP, depois pra Expedição". O sub-menu esconde as abas dos outros módulos — saindo de Cadastros pro PCP você perdia a trilha do que estava aberto e tinha que caçar tudo de novo no menu.
📑 Agora tem uma BARRA das telas abertas, logo abaixo do menu: cada tela que você abre entra ali como uma aba e atravessa os módulos — Clientes · Caixas · PCP · Expedição, lado a lado. Clica e troca na hora; o ✕ tira da barra.
💾 Volta do jeito que você deixou: a troca é instantânea porque nenhuma tela é recarregada — o filtro, a busca e o que estava digitado continuam lá. E as abas voltam quando você abre o sistema de novo neste computador (só a lista de telas fica guardada, nada de dado).
⧉ Segunda janela: o botão ⧉ de cada aba abre aquela tela numa janela nova — dá pra deixar o PCP num monitor e a Expedição no outro. A janela abre direto na tela certa (o endereço leva #view=).
⚠️ Cada janela é um sistema inteiro: baixa a carteira de novo e fica sincronizando sozinha. Serve pra comparar duas telas — não vale deixar meia dúzia aberta.
🛡️ A barra respeita o seu acesso: tela que o seu perfil não enxerga não entra (e some da barra guardada se o acesso mudar). No celular ela rola de lado. E se este pedaço não carregar, o sistema funciona exatamente como antes — ele só navega, não mexe em dado nenhum.
🔄 App preso numa versão velha — a causa raiz. Quando um aparelho se atualizava, ele recarregava numa endereço com a hora no fim (?v=1787016296684). Só que o sistema de cache tratava todo endereço com ?v= como "pode guardar pra sempre" — regra que vale pros arquivos de código (lá o número é a impressão digital do arquivo), mas não pra página, porque hora não é conteúdo. Resultado: depois da primeira atualização, o aparelho passava a morar num endereço que ele mesmo congelava — abria a tela velha mesmo com internet boa. Testado no ar: o endereço com ?v= devolvia a página velha, e o mesmo endereço sem ele devolvia a nova. Agora o cache guarda só arquivo; página é sempre buscada fresca. A economia de 2,5 MB por abertura continua igual.
🔔 Dois apps não avisavam de versão nova: o do Encarregado e o Almoxarifado da Cartonagem mostravam o número da versão na tela mas nunca ofereciam atualizar — quem usava só trocava de versão se alguém mandasse. Agora avisam igual aos outros.
⏱️ Compras e Manutenção só conferiam versão nova de 5 em 5 minutos; agora também conferem ao voltar pro app, como os demais.
⏳ "Não aprovou agora" deixou de virar "o cliente não quis". O aceite marcava como recusada toda caixa que ficasse desmarcada — e recusada sai do jogo: some do botão de gerar e nunca mais vira pedido. Mas a vida é a do KIMETAIS Nº 0011: o cliente fechou 1 das 7 e as outras 6 voltam depois, quando ele for colocar o pedido. O cartão dizia "6 o cliente não quis" numa venda que ainda estava de pé.
☑️ Agora são três situações por caixa: ✓ aprovada agora · em aberto (nem sim nem não — continua valendo) · ✕ o cliente não quis. Só o botão ✕ não quis, na tela de aceite do PCP, grava a recusa. O app do vendedor e o link do cliente só carimbam o sim — nenhum dos dois decide que o cliente desistiu.
🏭 Na tela de Gerar caixas + pedidos, as aprovadas nascem com o ✓ e as em aberto aparecem marcadas ⏳ EM ABERTO, desmarcadas: dá pra gerar (é só marcar), mas ninguém manda pra fábrica sem querer o que o cliente ainda não fechou. Quando ele voltar e fechar mais caixas, elas estão lá.
📲 O app do vendedor e o link do cliente falam a mesma língua: "as outras ficam em aberto — dá pra aprovar depois", e o cartão mostra quais são.
📦 De quebra, o Desenvolvimento passou a perguntar MODELO, FECHAMENTO e PALETIZAÇÃO. São decisões que se tomam montando a amostra — se é maleta ou meia maleta, se cola ou grampeia, quantas caixas vão no amarrado, que altura o palete pode ter e se a caixa vai aberta. Tudo isso viaja junto quando a caixa vira pedido: o cadastro nasce (ou se atualiza) com essas informações em vez de ficar pela metade.
🧮 O lastro e as camadas continuam sendo calculados pelo cadastro da caixa, que é quem já faz essa conta e desenha o palete — duas contas de paletização no sistema é o caminho pro número divergir.
📱 Os campos novos estão nas duas telas: no sistema e no app do Desenvolvimento no celular.
🆕 Caixa NOVA do Desenvolvimento agora vira cadastro ao virar pedido. Fecha o outro lado da v2.37.414: a caixa aprovada entrava na fábrica com um código que não era caixa nenhuma — o orçamento, a paletização e o app do operador não achavam nada, e alguém tinha que redigitar tudo no cadastro depois (quando lembrava).
☑️ Na tela de 🚀 Lançar pedido, quando a caixa não existe no cadastro, aparece "🆕 Criar o cadastro de CX FORTYS 2x5 para FORTYS" com o que vai junto: medidas, composição (com onda, gramatura e coluna), preço de referência, clichê e faca e o PDF da arte. Vem marcado; é lançar o pedido que a caixa nasce.
⚠️ Só o que o desenvolvimento sabe. Modelo, fechamento e paletização não vêm daqui — o quadro avisa pra completar em Cadastros ▸ Caixas. Inventar esses campos seria pior que deixar em branco.
🔁 De quebra, a caixa passou a ser reconhecida mesmo sem o vínculo: quando o item não tem o elo gravado (proposta de antes da v2.37.412, ou caixa que alguém cadastrou na mão), o sistema acha pelo código + cliente, os dois exatos — e aí mostra o quadro de atualizar em vez de criar caixa repetida. Mesmo código em outro cliente nunca casa.
🛡️ Não cria caixa sem código nem sem cliente, não cria duas vezes, e grava depois do pedido: cadastro que falhe ao salvar não segura produção.
📋 A v2 virou pedido — e agora o CADASTRO da caixa se atualiza junto. O Desenvolvimento existe pra mexer na caixa (medida, material, arte), mas o cadastro — que é o que o orçamento, a programação e o app do operador leem — continuava com o que estava lá antes. A caixa rodava a versão nova na fábrica com a arte velha no cadastro, e ninguém percebia até o operador abrir a tela dele.
☑️ Como ficou: na tela de 🚀 Lançar pedido aparece um quadro com o que o desenvolvimento tem de diferente do cadastro, linha por linha — "Largura interna: 500 → 520 mm", "Composição: ONDA B 357 → ONDA BB 520", "PDF da arte: LAYOUT v1 → 29-06 LAYOUT v2". Vem marcado; é só lançar o pedido que o cadastro se atualiza junto.
🧯 Nada acontece calado. Cadastro de caixa mexe em preço, paletização e chapa — por isso cada mudança está escrita, o ✓ dá pra desmarcar, e se a caixa já estiver igual ao desenvolvido a tela diz isso em vez de oferecer botão.
🎨 As cores do cadastro não são tocadas (a caixa guarda cor por nome cadastrado e o desenvolvimento guarda texto livre — escrever ali apagaria a cor certa).
⚠️ Se a onda mudar junto com a chapa, o quadro avisa que a composição de papéis do cadastro precisa ser conferida — a lista de papéis não vem do desenvolvimento, e gramatura órfã quebra a conta da onduladeira em silêncio.
🔗 Só a caixa amarrada pelo cadastro (as v2, v3… da v2.37.412) entra nessa conta: caixa nova não tem cadastro pra atualizar, e nada casa por nome. A chapa é achada pelo código, que é chave única — se não achar exatamente uma, a composição fica de fora em vez de trocar a chapa errada.
🛡️ O cadastro é gravado depois do pedido: se ele falhar ao salvar, o pedido já está na carteira e a tela avisa — atualizar cadastro nunca segura produção.
👁️ Agora dá pra VER a arte da caixa. No cadastro (seção 6.5) dava pra subir e pra remover, mas não pra abrir: o PDF ficava ali como um nome e um tamanho — "29-06CX FORTYS 2x5 LAYOUT.pdf · 271 KB" — e pra conferir tinha que caçar o arquivo no e-mail de novo. Entrou o botão 👁️ Ver na imagem e o 👁️ Ver PDF, ao lado do Remover.
🔎 Abre o que está na tela: se você acabou de escolher outro arquivo, é ele que abre — e não a arte antiga que ainda está salva. Caixa sem arte avisa em vez de abrir uma aba em branco.
🧯 Detalhe que quebraria calado: o Chrome bloqueia abrir arquivo em data: numa aba nova (proteção contra golpe) — a aba abriria em branco, sem erro nenhum. Arte que ainda não subiu pro servidor mora exatamente assim, então ela é convertida antes de abrir. Arte já no servidor abre direto.
📱 No app do Desenvolvimento (celular), caixa que já existe também entra como VERSÃO — o mesmo que o sistema ganhou na v2.37.412. Escolhido o cliente, o campo de referência sugere as caixas cadastradas dele; escolhendo uma, vêm medidas, composição e cores, a linha avisa "🔁 Caixa já cadastrada — alteração, entra como v2" e o cartão da caixa mostra o selo 🔁 v2. Nome que não está no cadastro continua sendo caixa nova.
📷 Igual ao sistema: caixa que já existe não pede amostra física de novo (fica desmarcado, à vista), e caixa nunca atravessa de cliente — trocar o cliente desfaz o vínculo sozinho.
🔁 No Desenvolvimento, caixa que já existe agora entra como VERSÃO — não como caixa nova. Boa parte do trabalho ali não é produto novo: é caixa aprovada que volta com mudança na arte. A referência era um campo em branco, então quem registrava redigitava medida, composição e cores de uma caixa que já está no cadastro — e a proposta nascia sem elo nenhum com as anteriores: a MESMA caixa aparecia 3 vezes na tela como se fossem 3 caixas diferentes.
📋 Como ficou: escolhido o cliente, o campo referência / nomenclatura passa a sugerir as caixas cadastradas dele (o mesmo cadastro que o orçamento usa). Escolhendo uma, vêm juntos medidas, composição e cores — só onde o campo está vazio, o que você digitou na mão fica.
🆕 Caixa nova continua igual: é só escrever um nome que não está no cadastro. A tela avisa qual dos dois casos é ("🔁 Caixa já cadastrada" ou "🆕 caixa nova").
v2, v3… A alteração entra como versão da mesma caixa: o cartão dela ganha o selo 🔁 v2 e a linha "📚 Versões anteriores desta caixa", com link pra abrir cada proposta antiga. Na lista, a proposta mostra quantas caixas são alteração.
🧮 A versão é contada na hora, nunca guardada — mesma regra da versão da arte. Se uma proposta antiga for apagada, a numeração se acerta sozinha em vez de ficar mentindo.
📷 Caixa que já existe não pede amostra física de novo (a amostra é a caixa aprovada lá atrás): o ✓ vem desmarcado, à vista, e é um clique pra remarcar se esta rodada também pedir amostra. A impressão (arte) continua marcada, que é justamente o que mudou.
🛡️ Caixa nunca atravessa de cliente: a CX 09 do KIMETAIS e a CX 09 do FK são caixas diferentes e contam versões separadas. Trocar o cliente na proposta desfaz o vínculo sozinho.
🔗 Agora o CLIENTE também escolhe as caixas, no link de aprovação. Fecha a corrente que começou na v2.37.387: as três portas do aceite — PCP, app do vendedor e link do cliente — aprovam caixa a caixa. Antes, no link era tudo ou nada: o cliente clicava em "aprovar" no orçamento inteiro e depois ligava pedindo pra fábrica não fazer 6 das 7 caixas.
☑️ Como ele vê: cada caixa do orçamento ganhou um ✓ (todas marcadas). Ele desmarca o que fica pra depois e lê embaixo "Você está aprovando 1 de 7 caixas · R$ 8.972,36", com o aviso de que as outras não serão produzidas. Na hora de assinar, a tela repete quantas caixas ele está aprovando.
✅ Depois de aprovado, o mesmo link mostra o que entrou (✓ aprovada) e o que ficou de fora (✕ não aprovada), com o nome, o cargo e a data de quem aprovou — vale como registro pros dois lados.
🛡️ O servidor CONFERE a escolha, não obedece. O que chega do navegador do cliente é conferido contra o orçamento que está no banco, pela referência da caixa: se o orçamento foi reeditado depois de o cliente abrir a página, a caixa certa continua sendo a certa, e caixa que não bate é descartada (nunca recusa no chute) e cai num aviso pro PCP conferir antes de gerar.
🏭 O aceite parcial do cliente chega no PCP igual ao do vendedor: as caixas recusadas aparecem apagadas na tela de 📋 Gerar caixas + pedidos e não viram produção; as outras continuam disponíveis se ele fechar depois.
⚠️ Esta entrada precisa do reinício do servidor (a conferência mora na API) — e a tela sabe esperar: o ✓ por caixa só aparece depois que a API responde que sabe recebê-lo. Antes do reinício, o link do cliente funciona exatamente como funcionava, aprovando o orçamento inteiro. Sem essa espera, o cliente escolheria 1 de 7 caixas e a fábrica faria as 7, sem ninguém perceber.
⚖️ A conta do papel agora FECHA — rolo por rolo. No relatório Perda de Papel tem um quadro novo com as quatro colunas que o dono pediu: quanto entrou na máquina, quanto usou pra fazer a chapa, quanto sobrou de toco e o que não fecha. Em cima os totais do período, embaixo a lista rolo a rolo, do que mais destoa pro que menos.
📏 Os três primeiros números não são estimativa: o que entrou é a balança na conferência da nota, o que sobrou é a balança no "Voltou da máquina", e o que usou são os metros que os lançamentos descontaram daquele rolo. A diferença é o que sobra — e é ela que aponta onde o papel está indo embora.
🎯 Cada linha mostra a máquina, quantos lançamentos comeram aquele rolo e a diferença em kg e em %: verde quando fecha (até 5%), amarelo quando escapa, vermelho acima de 15%.
↩️ Se a conta der negativo — mais papel apontado do que entrou nos rolos — a tela diz isso na cara e explica a causa provável: rolo rodando sem ter sido fechado na balança, ou produção lançada no rolo errado.
🤐 Rolo fechado antes desta conta existir (sem o "usou" gravado) fica fora do total, com "—" na coluna, e a tela conta quantos são. Entrar com zero faria o "não fecha" aparecer gigante e mentiroso. Rolo fechado de agora em diante já entra sozinho.
🔄 Mexeu no orçamento, o cliente vê o número novo no link do Desenvolvimento. Até agora não via: quando a caixa era trazida pro Desenvolvimento, o sistema tirava uma fotografia do orçamento e o link do cliente mostrava essa foto pra sempre. No KIMETAIS Nº 0011 o cliente continuava vendo 3.000 caixas · R$ 16.617,85 depois de o orçamento virar 1.620 caixas · R$ 8.973,64 — e reenviar o link não adiantava nada.
🧮 A conta do papel do cliente agora FECHA. O documento levava só a caixa da proposta, mas o subtotal, o total e o peso eram do orçamento inteiro (as 7 caixas do KIMETAIS): item R$ 16.617,85 e subtotal R$ 79.282,08 na mesma folha. Agora subtotal, IPI, ferramenta, total e peso são refeitos só com as caixas daquela proposta.
💰 O preço do cartão e o do documento saem da MESMA linha — o cliente nunca mais vê dois valores diferentes na mesma tela.
🔎 Nada é chutado. A caixa da proposta é casada com a linha do orçamento por referência + medidas, e a partir de agora também pela posição gravada na hora de trazer pro Desenvolvimento. Se a mesma caixa aparecer em várias quantidades e não der pra ter certeza qual é, fica o valor de antes — número velho é ruim, número chutado é pior.
🛡️ Se o orçamento tiver sido apagado, o documento sai como saía, com a cópia guardada na proposta. O cliente nunca abre um papel em branco.
🤝 O vendedor agora aprova o orçamento CAIXA A CAIXA, pelo celular. O cliente quase nunca fecha tudo: o KIMETAIS Nº 0011 tem 7 caixas e ele comprou uma. Aqui no sistema dava pra escolher desde a v2.37.387, mas no app do vendedor era tudo ou nada — ele tinha que ligar pra central pra dizer quais caixas valiam.
☑️ Como ficou: ao tocar em "🤝 Cliente aprovou" abre uma tela com as caixas do orçamento, cada uma com um ✓. Ele desmarca as que o cliente não quis, e embaixo aparece ao vivo "1 de 7 caixa(s) aprovada(s) · R$ 8.972,36" com o aviso de quantas ficam de fora. Só depois ele escreve quem aprovou e envia.
🏭 O que chega na fábrica é só o que foi vendido. O aceite parcial cai direto na tela de 📋 Gerar caixas + pedidos: as recusadas aparecem apagadas com "✕ o cliente não quis" e não viram pedido. As que sobraram continuam disponíveis se o cliente fechar depois.
🔎 O elo é a REFERÊNCIA da caixa, não a posição na lista — se o orçamento foi reeditado depois de mandar pro vendedor, a caixa certa continua sendo a certa. E se ele recusar uma caixa que já virou pedido, ou uma que sumiu do orçamento, o sistema não chuta: o cartão avisa "confira antes de gerar".
📲 A conversa vai e volta: aceite parcial registrado aqui no PCP também aparece no app dele, com as caixas marcadas e o selo "🤝 Aceito (parcial)" no cartão — o vendedor não cobra o cliente por caixa que ninguém pediu.
🛡️ Orçamento aceito por inteiro se comporta exatamente como antes, e aceite antigo (de antes desta versão) continua valendo pelo orçamento todo.
⚖️ O aviso de falta de papel, na hora de fechar o rolo. Aquilo que o dono pediu: "se a máquina carregou 5.000 kg, dava pra fazer 5.000 chapas, foi apontado 4.000 e ninguém lançou refugo, tem que avisar que está faltando papel". Agora, quando o operador pesa o toco na balança, o app compara na hora e mostra: "⚠️ Faltam 128 kg de papel (29% do rolo) — o rolo comeu 443 kg e só 315 kg viraram chapa apontada", com os pedidos que apontaram.
🧮 A conta é de dois números MEDIDOS e um derivado, sem estimativa: o que o rolo comeu sai da balança (peso de entrada − peso do toco), e o que foi apontado sai dos lançamentos que descontaram aquele rolo — cada lançamento da onduladeira já deixa registrado quantos metros tirou. É rolo por rolo, não média do mês.
🔕 Não vira alarme falso: só fala acima de 20 kg E 5% do rolo. Diferença pequena aparece como "✅ bate com o que o rolo comeu".
🤐 E não acusa ninguém. A tela diz que o papel não está apontado — pode ser refugo, emenda ou parada — e pede pra lançar a ocorrência. Se ninguém apontou nada com aquele rolo, ela diz isso com todas as letras. Se a internet cair, ou se o rolo estiver sem largura ou gramatura no cadastro, ela fica calada em vez de acusar falta que não sabe medir.
📌 O número fica gravado no fechamento (kg apontado, metros e a falta), então o PCP e o relatório de perda leem depois sem precisar refazer a conta.
📏 A régua da bobina, na tela da onduladeira. Cada rolo lido ganhou uma barra fatiada por pedido: cada fatia é do tamanho do que aquele cliente come daquele rolo, na cor dele, com o nome e os metros escritos dentro — e no fim a fatia hachurada do toco. São 3 barras na onda B e 5 na BB, uma por papel da chapa (capa, miolo, contracapa…), na mesma ordem dos campos de leitura.
🪵 Diz quanto de toco vai sair, em metros e em quilos: "vai sobrar toco de 1.849 m ≈ 208 kg". E se a fila não couber no rolo, avisa em vermelho: "não sobra nada — falta ~464 m", antes de o papel acabar no meio do pedido.
▶️ Ao vivo: o pedido que está rodando fica com a borda branca e uma faixa dentro da fatia mostrando quanto já saiu (350 de 589 chapas · 59%). Quando o vizinho lança produção no mesmo rolo, as fatias se atualizam sozinhas — sem redesenhar o card, então nada do que o operador digitou se perde.
🏷️ Em cima, a legenda com cada cliente: ▶ rodando, reservado (o PCP escolheu esse rolo) ou serve (só combina de gramatura e largura).
🧮 De quebra, um erro de conta foi corrigido: quando capa e contracapa têm a mesma gramatura (Kraft 90 nas duas, que é o normal), o sistema contava o mesmo rolo nas duas camadas e dizia que ele comia o dobro — 866 m onde o certo eram 433. Um rolo ocupa uma posição na máquina: agora conta uma camada só, e o toco previsto sai certo.
🛡️ Nada saiu do lugar: a programação, os vincos, os papéis pra pegar e os campos de leitura do QR continuam iguais — a régua é um bloco a mais embaixo de cada papel.
🔁 Um rolo, vários clientes — a onduladeira passou a mostrar isso. O mesmo rolo roda o pedido de um cliente e emenda no do outro, mas a tela era por pedido: o operador lia o rolo, lançava, voltava pra fila e não tinha como saber que aquele rolo ainda ia servir outro cliente. Agora, na hora que ele lê o QR, aparece embaixo "🔁 Este rolo também atende:" com os clientes, o pedido de cada um e quantos metros cada um vai comer.
➡️ E depois de lançar, o app oferece emendar. Se o rolo ainda tem papel e ainda serve alguém, em vez de voltar pra fila sozinho aparece o botão "Ir pro próximo pedido desta bobina" — com o saldo do rolo e o consumo do próximo escritos ali. Se o rolo acabou, ele volta pra fila como sempre fez.
⚠️ A tela separa o que é certeza do que é palpite: pedido marcado "reservado" é o que o PCP escolheu pra aquele rolo na Programação (é elo por identidade, não por nome); "serve" é sugestão — mesma gramatura e mesma largura. E quando o saldo do rolo não cobre a fila toda, a linha do que não cabe fica em amarelo.
🧮 O consumo mostrado é só das camadas que aquele rolo atende: um rolo de 180 g num pedido de capa 180 / miolo 140 conta as duas capas e não o miolo, que é outro rolo. E no rolo de miolo entra o fator da onda, como no resto do sistema.
🛡️ Nada disso desconta nada sozinho: o papel continua baixando só no rolo que o operador leu, no pedido que ele lançou. É informação na tela, não movimento no estoque.
🧾 A empilhadeira recebeu a lista de separação. O app Estoque de Bobinas ganhou a aba "🧾 Separar pra onduladeira": os pedidos programados aparecem em ordem de entrega, cada um com os rolos que o PCP reservou e a posição de cada um na máquina (capa / miolo / contracapa). O empilhadeirista bipa o código (ou aperta "dar saída") e o rolo sai do estoque direto pra Onduladeira, com o nome de quem separou.
🔢 Um número na aba mostra quantos rolos ainda faltam separar, e cada pedido mostra "2/3 separados".
⚠️ O estado de cada rolo vem do estoque, não do papel: se o rolo que o PCP escolheu já saiu, já foi consumido ou sumiu do estoque, a linha diz isso e não deixa dar saída de novo. Bipou um rolo que não é da lista? Avisa — mas não trava: é só usar a aba 🏗️ Saída, como sempre. Dois aparelhos ao mesmo tempo não dão baixa duplicada.
♻️ A lista sai sozinha quando o pedido é reprogramado ou já virou chapa — não fica tarefa velha esperando alguém cancelar. Pedido programado sem rolo escolhido simplesmente não aparece, e a empilhadeira puxa pela gramatura como sempre fez.
🔗 Fecha a corrente Programação (escolhe) → Separação (puxa) → Onduladeira (consome pelo QR) → Voltou da máquina (pesa o toco).
🎯 A programação passou a dizer QUAIS rolos vão ser puxados — e quanto vai sobrar de toco. Na tela de Programar, cada camada agora mostra: "vai puxar JP-BOB-0048 + JP-BOB-0051 → sobra 578 m", e quando a sobra é pequena avisa que vira 🪵 toco. Quem escolhe é o sistema (rolo mais velho primeiro, pra girar o estoque), mas o PCP troca na mão em "trocar rolo" — e tem o botão de voltar pra sugestão.
🔒 Ao programar, esses rolos ficam RESERVADOS pro pedido e somem da sugestão dos outros. Se outro pedido tentar usar, a tela mostra "🔒 reservado pro pedido 23489" em vermelho, com o número de quem pegou primeiro.
♻️ A reserva se solta sozinha. Ela não é um carimbo no rolo: vale enquanto o pedido estiver programado. Pedido reprogramado, cancelado, ou que já virou chapa libera o rolo na hora — ninguém precisa lembrar de destravar, e não existe rolo preso por engano.
⚠️ E avisa quando não fecha: se os rolos marcados não cobrem os metros da rodada, aparece "os rolos dão 1.300 m e a rodada gasta 1.950 m — falta papel".
ℹ️ Nada trava e nada baixa aqui: a reserva é um combinado do PCP, e o metro só sai do rolo quando a onduladeira lê o QR dele. Próximo passo (já em andamento): o app Estoque de Bobinas vai receber essa lista pronta — "separar pra onduladeira" — com os rolos, a posição de cada um (capa / miolo / contracapa) e o pedido, pra empilhadeira puxar sem perguntar pra ninguém.
🪵 O toco virou rolo, com etiqueta própria. Quando o rolo não acaba na máquina, o operador pesa o resto na balança (app Estoque de Bobinas ▸ 🔙 Voltou da máquina). Até agora o resto voltava pro estoque com o mesmo número e a etiqueta velha colada — o sistema sabia o saldo e o papel colado no rolo dizia o peso da entrada. Agora o rolo antigo é encerrado e nasce um rolo novo, com número próprio, marcado TOCO, com o mesmo cliente, papel, gramatura e largura, e só o que sobrou de peso e metros. A etiqueta abre sozinha na hora de fechar — é só imprimir e colar.
🧮 Isso conserta um buraco na conta de perda: um rolo só pode ser fechado uma vez. Como o toco voltava com o mesmo número, na segunda vez o app dizia "esse rolo já foi fechado" e o papel que ele comeu na segunda vida nunca entrava na conta. Agora cada vida do papel é um rolo, pesa e fecha sozinha.
🔗 O rolo novo fica ligado no rolo que o gerou — dá pra seguir a linha do papel desde a nota fiscal.
🛡️ Nada de papel sumindo calado. São 5 passos (registrar o fechamento · criar o rolo novo · encerrar o velho · baixar os kg · imprimir), e a ordem foi escolhida pra toda falha cair pro lado seguro: se a internet cair antes de o rolo novo nascer, o rolo velho continua inteiro no estoque. Se parar no meio, aparece um aviso vermelho com o botão "▶️ Terminar o fechamento", que refaz só o que faltou — apertar de novo nunca cria dois rolos nem baixa o papel duas vezes.
🔎 E se o aparelho desligar no meio, o app acha sozinho: na lista de rolos fechados aparece "🪵 Toco de X sem rolo", com o botão pra criar o que faltou.
ℹ️ O estoque em kg não muda com isso: o papel do toco nunca saiu do livro, só trocou de rolo.
🧻 A programação passou a mostrar as bobinas que existem no estoque. Na hora de programar, o PCP escolhia o papel e a largura da bobina sem ver o que tem no galpão — quem descobria era a onduladeira, na hora de rodar. Agora, dentro da tela de Programar, tem um quadro que procura, camada por camada, os rolos daquela gramatura: quantos são, em que largura, quantos metros, de quem é o papel e o código de cada rolo.
🎯 A lista de larguras agora diz o que existe: "1400 mm · 29 rolos", "1350 mm · sem rolo". Antes eram só as medidas.
⚠️ E avisa três coisas diferentes, que não são a mesma: ✅ tem rolo na largura escolhida (com os metros, comparados com o que a rodada gasta) · ⚠️ tem o papel, mas em outra largura (e diz em qual) · ❌ não tem nenhum rolo dessa gramatura.
🔎 O que a conferência mostrou hoje (16/08): das 83 camadas das 25 chapas cadastradas, só 5 têm rolo com a gramatura certa disponível. Todo o estoque disponível (48 rolos) é papel do DCX PACKAGING, e só de 140, 180 e 220 g — as chapas usam 100, 110, 120 e 130 g. Os 22 rolos de papel branco da JP (1.350/1.370 mm) estão marcados como "saíram pra Limpeza de teste", então não contam como estoque. O sistema não estava errado; o cadastro é que não conversava com o galpão.
🛡️ Regras que ficam claras: a procura casa por gramatura exata + largura (com 5 mm de folga), a MESMA regra que a onduladeira usa quando lê o QR do rolo — o nome do papel na nota ("BARILE TOP LINER") aparece escrito, mas não decide nada. Rolo que saiu pra outro destino não entra na conta, e rolo que já está na onduladeira aparece à parte (🏭). Se a internet falhar, a tela diz que não conseguiu conferir — nunca diz que não tem.
ℹ️ Isso é só conferência: nada é reservado e nenhum metro baixa aqui. O estoque continua baixando num lugar só — quando a onduladeira lê o QR do rolo.
🪜 O pedido e as reprogramações dele agora ficam juntos. Quando um pedido roda pela metade, o que sobra vira um pedido novo — e na Carteira eles apareciam como duas linhas soltas, uma "Entregue" e outra "Reprogramado", sem nada ligando uma na outra. Pior: o registro do que foi feito morava num pedido e o do que falta morava no outro.
👉 Como usar: na coluna da quantidade apareceu um botão 🪜 (N rodadas). Clicou, abre embaixo a escada da encomenda: rodada 1, rodada 2, rodada 3… em ordem, cada uma com o status dela. O botão aparece nas duas linhas e abre a mesma escada — tanto faz por qual você entrar.
📋 Cada rodada mostra: a chapa lançada, a produção máquina por máquina com o nome do operador, quantos paletes foram etiquetados, quando saiu do PA / carregou / entregou, a baixa daquela rodada e quanto sobrou pra rodada seguinte. Em cima, o resumo: pedido do cliente, já produzido, já entregue, pronto no PA e o que ainda falta.
🧾 Registro anulado não polui — fica escondido atrás de um "👁️ ver anulados", riscado, pra quem quiser conferir.
📅 Entrega programada não vira rodada. O nº do pedido do Sectra se repete no contrato: a caixa 44959 do FK GRUPO tem nove pedidos com o mesmo número, com entrega até 05/10 — sete deles nunca rodaram. Isso é o programa de entregas combinado com o cliente, não reprogramação. Então só vira rodada quem já teve produção ou chapa lançada (mais o saldo reprogramado, que nasce vazio); o resto aparece no rodapé como "próximas entregas", sem entrar na conta de feito e falta.
🔒 Nada muda de lugar e nada é gravado. As linhas da Carteira continuam as mesmas, os status continuam os mesmos — a tela só lê e junta o que já existe. E nunca mistura cliente: o casamento é pela caixa, pelo material do Sectra ou pelo código exato, sempre dentro do mesmo cliente.
🔁 A mesma produção não é mais apontada duas vezes. Quando um pedido era finalizado e depois voltava — porque o PCP reabriu a etapa pra terminar o que faltava, ou porque o operador pegou de novo —, o app esquecia o que já tinha mandado e lançava a produção inteira outra vez. O gestor via caixa que nunca saiu da máquina.
📌 Aconteceu de verdade duas vezes: em 11/08 na TAMPA 10KG da Marilei (a etapa foi reaberta pra fazer 10 caixas e subiram 2.400 de novo — 4.800 apontadas num pedido de 2.000) e em 14/08 no 45284 (as mesmas 527 lançadas duas vezes, pelo botão "imprimir prontos e continuar").
🧮 Agora o app confere quanto ainda cabe na etapa antes de gravar, e desconta sozinho: lança só o que falta e mostra na tela do operador "já havia 2.400 cx apontadas nesta etapa — lancei só as 10 que faltavam". Ele fica sabendo na hora, não descobre depois.
🛡️ Só corta o que é repetição. A conta só entra quando o número que vai subir é maior ou igual ao que já está apontado — que é a cara de "mandei o total de novo". Produção que passou um pouco do previsto (sobra de chapa que rendeu mais caixa) não é tocada, e na dúvida — sem material lançado, ou o número do PCP ainda não publicado — o app deixa passar inteiro. Nunca prende produção real por falta de informação.
✅ Vale nos três caminhos que gravam produção — Finalizar, "🖨️ imprimir prontos e continuar" e o fechamento de fim de turno. Os dois últimos não passavam por aviso nenhum: era por eles que escapava. Quem responder "fiz as X sozinho mesmo" no aviso de contador acumulado continua sendo respeitado.
🧹 Limpeza do que já estava no banco: as cópias antigas que ainda contavam em dobro foram arquivadas (nada é apagado — dá pra desfazer). A produção, a produtividade por máquina e a perda por etapa voltam a mostrar só o que realmente saiu.
👥 Dois pedidos apareciam com exatamente as mesmas ocorrências e as mesmas fotos. Na Ficha do Operador, a ocorrência era colada na ficha por nome do cliente + data. Como no dia 14/08 o FK GRUPO teve 9 ocorrências espalhadas em 4 pedidos, todas as 9 apareciam em TODA ficha do FK daquele dia — o mesmo problema que já mordeu antes: casar por nome de cliente é o erro mais caro do sistema.
🎯 Agora cada ocorrência aparece uma vez só, no pedido certo — e na máquina certa: a que o operador apontou na Grampeadeira fica na ficha da Grampeadeira, a da Slotter na da Slotter. Se aquela máquina não rodou o pedido no dia, a ocorrência continua aparecendo na ficha que existe (nada some da tela).
📷 A foto não abria. Clicava na etiqueta 📷, a tela escurecia, aparecia o texto da ocorrência… e no lugar da foto ficava um pontinho. A foto estava lá e o servidor entregava ela certinho — quem quebrava era o desenho da janela, que espremia a imagem até quase zero. Refeito no mesmo formato da foto ampliada da tela de Ocorrências, que sempre funcionou.
🔴 E se um dia a foto não carregar, a tela diz isso ("não deu pra carregar esta foto") em vez de mostrar um ponto e deixar você adivinhando.
🔎 Busca na Programação. Eram 47 pedidos numa lista só, e achar um era descer a tela rolando. Agora tem um campo em cima: digite o número do pedido, o cliente, o código da caixa ou o código da chapa e a tela mostra só o que casa. Não precisa acento nem letra maiúscula ("maca" acha "MAÇÃ"), dá pra juntar duas palavras ("fk 19403") e o Esc limpa.
⏳ Aba nova: "Programados". Só o que já foi programado e está esperando a onduladeira fazer a chapa — agrupado por onda e bobina, com o botão "✅ Chapa produziu" em cada um.
✅ Aba nova: "Material disponível". Só o que já tem chapa pronta, liberado pra produção. Antes os dois moravam juntos na mesma fila lá embaixo e era preciso caçar pela etiqueta de cada card qual era qual.
🔢 As abas mostram quantos são (⏳ 12 · ✅ 5), então dá pra ver o tamanho de cada fila sem abrir.
🛡️ Nada do que existia mudou de lugar: a aba "📐 Programar" continua com a lista "A Programar" e a "🧵 Fila da onduladeira" embaixo, do mesmo jeito. As abas novas são atalhos pra ver cada metade sozinha — e a busca vale nas três.
🚫 Dava pra sair, entregar e voltar com o caminhão vazio. O motorista marcava "saí da fábrica", "cheguei" e "entreguei" com a carga nem bipada na Expedição — e o próprio app dele mostrava "⏳ Aguardando carga" na tela. Agora ele é avisado: "A carga ainda não foi bipada na Expedição. Sair mesmo assim?".
⚠️ Avisa, não trava (decisão do dono): carga montada na mão não pode prender o caminhão no pátio. Se ele seguir mesmo assim, fica registrado — a Escala e a "Entregas ao vivo" passam a mostrar "⚠️ saiu sem conferência" naquela viagem. Pergunta uma vez só por viagem, pra não virar praga.
🏁 Botão novo: "Cheguei na fábrica". Existia "saí" e "voltando pra fábrica", mas não existia o fim — a viagem ficava "voltando" pra sempre e ninguém no escritório sabia que o caminhão tinha encostado. Agora carimba a hora real (desmarcar pergunta antes, porque hora não volta) e aparece como "🏁 Chegou 23:10" na Escala e na Entregas ao vivo. Esse mesmo toque avisa a Expedição de todos os retornos de uma vez — antes era um botão por item.
📍 O motorista agora diz ONDE pôs a mercadoria — cabine, baú ou carroceria. Quem vai descarregar via só "chegou com coleta" e tinha que caçar no caminhão; agora lê "📍 está na CABINE" em laranja, no mesmo alerta.
🔄 A corrente do retorno agora fecha: quem pediu fica sabendo. A Compra lançava a retirada e nunca mais via nada — a caixinha dizia sempre a mesma frase ("retirada já lançada"), e o comprador tinha que perguntar pra alguém se o material chegou. Agora ela mostra onde a coisa está de verdade: esperando viagem → na viagem do fulano → o motorista pegou (📍 vem na cabine) → chegou na fábrica → retirada do caminhão → no almoxarifado → ✅ recebida, com a última linha do histórico dizendo quem fez e a que horas.
📋 Uma faixa no topo do app de compras mostra o que precisa de ação: em vermelho o que o motorista não conseguiu pegar, em verde o que chegou hoje, e o resto em andamento numa linha só.
⚠️ Botão novo pro motorista: "Não consegui pegar", que pede o motivo. Antes só existia o caminho de deu certo — se o fornecedor não entregou, a retirada ficava presa naquela viagem pra sempre. Agora ela volta sozinha pra fila "Retiradas esperando viagem" da Escala, com o motivo escrito, pra ser pendurada em outra viagem. A Escala mostra por que voltou — senão penduraria de novo na mesma viagem sem saber que já tinha falhado.
🕐 O almoxarifado passou a carimbar o dia do recebimento. A ficha não guardava data de chegada nenhuma (só a hora, sem o dia), então "chegou hoje" não teria como ser verdade — o comprador abriria o app de manhã e não veria o que chegou de noite, justamente o caso que importa.
📥 O retorno chega no almoxarifado do JP Microondulados — a tela dele passou a mostrar "📍 está na CABINE", pra quem recebe saber onde procurar no caminhão, sem precisar caçar. O almoxarifado da Cartonagem (que controla os insumos exclusivos dele) ganhou a mesma tela pronta e vazia, de reserva: é só ligar no dia em que vocês quiserem separar os dois. Retirada antiga, sem marca, cai no Microondulados — retorno que não aparece em almoxarifado nenhum é pior que retorno no lugar errado.
🚨 De quebra, achamos o app do almoxarifado da Cartonagem QUEBRADO — e consertamos. Desde 04/08 ele não abria: uma linha de impressão fechava o programa no meio, sem dar erro em lugar nenhum. Quem tentasse usar via a tela montada e nada funcionava. Passamos a conferir todos os 21 apps por esse defeito — só esse estava com ele.
🛡️ Nada do que já existia mudou: a corrente Compras → Escala → motorista → Expedição → Almoxarifado continua igual, e retorno antigo (sem os campos novos) aparece do mesmo jeito.
🚛 As duas entregas do motorista agora são iguais. A entrega podia chegar por dois caminhos — pela carga bipada na Expedição ou pela escala — e o app tratava cada uma de um jeito. A da escala tinha endereço, rota, "Cheguei" e "Saí da fábrica"; a da carga bipada tinha só o botão "Entreguei este". O motorista não escolhe por onde a entrega entrou no sistema: pra ele é a mesma entrega.
📍 A carga bipada ganhou tudo: o endereço do cliente, os botões 🧭 Rota e 📞 Ligar, o 🗺️ Seguir a rota com as paradas que ainda faltam, o 📍 Cheguei e o 🚚 Saí da fábrica.
🛡️ Chegar não é entregar. O "Cheguei" é só uma marca de caminho — o pedido não é dado por entregue, e o escritório só recebe a entrega quando ele apertar "Entreguei este". Se ele marcar a chegada e depois entregar, a hora da chegada fica guardada.
⏱️ Desmarcar a saída pergunta antes, porque a hora real não volta — mesma regra da escala.
🔁 Entrega antiga continua aparecendo igual, e cada marca é gravada sozinha: dois motoristas usando ao mesmo tempo não apagam um ao outro.
🏦 Botão novo em Cadastros → Clientes: "Crédito e prazo". Ele mostra de uma vez só quem está sem limite de crédito e quem está sem prazo de pagamento, com um ✏️ pra preencher na hora. Conferindo o cadastro de verdade hoje: dos 36 clientes ativos, nenhum tinha limite e só 2 tinham condição de pagamento — por isso o aviso de limite não aparecia pra ninguém. Não era falta de sistema, era falta de cadastro, e não dava pra saber disso sem abrir as 36 fichas uma a uma.
📅 O vencimento agora aproveita o "prazo padrão" do cadastro. São dois campos diferentes na ficha do cliente — condição de pagamento e prazo padrão — e o sistema só olhava a condição. Quem tinha só o prazo (DEUSA 20 dias, ECOLUBRI 10, ENERBRAX 15) gerava conta a receber "à vista, vencendo hoje", e a Previsão de caixa saía errada com o cadastro preenchido. Agora, sem condição, vale o prazo.
⚖️ Quando o cliente tem os dois, vale a condição de pagamento (ela carrega o parcelamento, tipo "28/35/42"; o prazo é um número só). É o caso do KININO, que tem prazo 15 e condição 35 dias — a tela nova mostra isso escrito, pra ninguém ficar na dúvida.
ℹ️ Cliente inativo não entra na lista de pendências, e quem não tem nada cadastrado continua vencendo à vista, como antes.
🔗 Agora dá pra resolver cliente cadastrado duas vezes. Em Cadastros → Clientes entrou o botão "🔗 Juntar repetidos": ele acha sozinho os cadastros com o mesmo nome — mesmo escritos diferente ("GRS TOYS" e "GRS Toys LTDA", "ALPACK" e "alpack") — e mostra quantos pedidos e caixas cada um tem.
➡️ Você escolhe qual fica, e tudo do repetido passa pra ele: pedidos, caixas, orçamentos, amostras, notas fiscais e o estoque de papel. Aí o repetido é apagado.
👀 Antes de mexer, ele mostra a lista. Pedido por pedido, com número, caixa, quantidade e valor — "23532 CX 09 — 5.000 cx · R$ 12.400,00 (entregue)". Só grava depois que você confirma, e não tem desfazer, então confira com calma.
🔒 Por que não era só apagar: o botão de excluir já funcionava, mas ele se recusa quando o cliente tem pedido — e com razão. Apagar assim deixaria pedido entregue apontando pra um cliente que não existe mais, sem avisar, levando junto a comissão do vendedor. Por isso o certo é juntar primeiro.
📄 Estoque de papel: se os dois cadastros tinham o mesmo papel, os saldos são somados — o papel é físico e pertence a um cliente só.
⚙️ Precisa do Luan reiniciar a API pra este botão funcionar (é rota nova no servidor). Enquanto isso não acontece, o botão avisa direitinho: "a API do servidor não foi atualizada" — e nada é alterado.
🔗 O Plano de Carga agora puxa o caminhão da Escala. As duas telas existiam e não se falavam: no Plano você escolhia um caminhão do cadastro, e o sistema ia procurar uma viagem pra ele.
🕵️ O que estava acontecendo de verdade: a viagem de verdade quase sempre nasce pelo caminho do caminhão de terceiro, em que o motorista digita a placa na hora — e aí ela fica com um caminhão que não está no cadastro. Conferido no sistema: a única viagem (REINALDO · ACH9A34) apontava um caminhão que não existe no cadastro, e o Plano só oferecia o "Dag verde". Resultado: escolhia o caminhão, e o plano respondia "sem viagem" — sempre.
🗓️ Agora a lista mostra as VIAGENS: "16/08 · REINALDO · ACH9A34 · 1 entrega". Escolhendo a viagem, o plano já sabe o caminhão, a placa, o baú e os clientes na ordem de entrega — sem procurar nada, e funcionando também com caminhão que não está no cadastro.
🎯 De quebra resolve o caminhão com duas viagens no mesmo dia, que antes o sistema escolhia sozinho e sem avisar. Agora você diz qual.
🚛 Quem monta a carga antes de escalar continua podendo: os caminhões do cadastro sem viagem aparecem num grupo separado, logo abaixo.
📐 O baú vem da viagem; se estiver em branco lá, busca no cadastro pela placa. Hoje ele está zerado nos dois lugares — vale preencher as medidas dos caminhões, senão o plano não tem como calcular o encaixe.
💾 Plano salvo antes desta versão continua abrindo igual.
🧩 Orçamento com várias caixas: agora o senhor aprova SÓ AS QUE O CLIENTE QUIS. Era tudo ou nada — o KIMETAIS Nº 0011 tem 7 caixas (R$ 91.174) e o cliente fechou uma; do jeito antigo, gerar pedido despejava as 7 na fábrica.
🤝 No "Registrar aceite" abriu uma tela com a lista das caixas do orçamento, cada uma com um ✓. Desmarque as que o cliente não quis — embaixo aparece, ao vivo, quantas caixas ele aprovou e quanto vale o negócio que o senhor está fechando.
📋 Na hora de "Gerar caixas + pedidos" cada caixa também tem um ✓, já marcado pelo que foi aceito. Só as marcadas viram pedido. As que o cliente recusou aparecem apagadas na lista, escrito "✕ o cliente não quis", e as que já viraram pedido, "✅ já virou pedido".
🔒 Caixa que já virou pedido não vira de novo, nem reabrindo o orçamento — a trava contra pedido em dobro passou a ser por caixa (antes era do orçamento inteiro).
♻️ O que sobrou não se perde: se o senhor gerar 2 caixas hoje, o orçamento continua na lista com o botão "📋 Gerar as 5 caixas que faltam" — o cliente pode fechar o resto depois, no mesmo orçamento e no mesmo número.
📊 O relatório de conversão passou a contar o dinheiro certo: a caixa vendida entra em "virou pedido", as recusadas em "perdido" e as que faltam em "a converter". Antes o orçamento inteiro (os R$ 91.174) contaria como vendido numa venda de uma caixa. Orçamento antigo não muda em nada — quem foi decidido em bloco continua exatamente como estava.
🏦 A tela de Baixa agora avisa quando o cliente passa do limite de crédito. O limite já existia no cadastro do cliente e só era usado no orçamento — mas a dívida nasce mesmo é na hora de faturar, porque é a baixa que cria a conta a receber. Agora, antes de dar baixa, o sistema mostra em números: "Limite R$ 30.000,00 · já em aberto R$ 28.400,00 · esta nota R$ 4.200,00 — passa R$ 2.600,00 do limite. Dar baixa assim mesmo?"
✅ Avisa, não barra. Vender acima do limite é decisão sua — o que não pode é acontecer sem ninguém ver. Se você mandar seguir, fica registrado na Vida do Pedido quem autorizou e com quais números, pra consulta depois.
👀 O aviso aparece também na lista, antes de você clicar: a linha do pedido mostra "🏦 Passa R$ 2.600,00 do limite". Assim dá pra ver de quem é o problema só de olhar a fila.
🧮 A conta é a mesma do orçamento (limite − o que o cliente já deve nas contas a receber em aberto), pra não existirem dois números diferentes de "quanto ele pode dever". Conta já paga não conta, e cada nota que você fatura hoje aperta o limite da próxima — como na vida real.
🤫 Cliente sem limite cadastrado não gera aviso nenhum. Limite em branco quer dizer "não definido", não "não pode dever nada" — inventar aviso pra todo mundo só ensinaria a clicar OK sem ler.
💰 O fluxo de caixa agora sabe QUANDO o dinheiro entra — e se foi antecipado. A previsão somava tudo pelo vencimento, ou seja, achava que todo boleto entra no dia que vence. Agora cada conta a receber pode ter Nº do boleto (o que você gera no site do banco) e previsão de entrada, e a Previsão de caixa de 8 semanas passou a usar a data de entrada, não a do vencimento.
🏦 Ao dar baixa numa conta a receber, o sistema pergunta o que importa: em que dia o dinheiro caiu, quanto caiu e se foi antecipado no banco. Marcando antecipado, ele calcula sozinho o desconto (a diferença entre o boleto e o que entrou) — assim ninguém precisa fazer a conta na mão nem digitar dois números que podem não bater.
📉 Quanto a antecipação custou aparece somado no mês, dentro da Previsão de caixa: "1 boleto · valor de face R$ 10.000,00 · entrou R$ 9.400,00 · custou R$ 600,00". Antecipar é dinheiro na frente pagando juro — e esse juro estava sumindo, cada boleto parecia só "entrou menos".
🧾 Um filtro novo: "A receber sem boleto" — a lista do que ainda falta gerar no banco, com cliente, valor e vencimento.
↩️ Desfazer a baixa limpa tudo junto (data, valor recebido e a marca de antecipado). Conta que volta pra "em aberto" com o dinheiro ainda marcado como recebido contaria duas vezes.
ℹ️ Conta antiga continua igual: sem previsão informada, a data de entrada é o vencimento — nada mudou de lugar sozinho. E, como sempre, dar baixa aqui não lança custo no Centro de Custo.
🧟 Laudo apagado voltava sozinho — e agora não volta mais. Na Qualidade trabalham 6 pessoas, e sempre tem um computador aberto. Bastava um apagar um laudo e outro salvar qualquer coisa pra tudo o que foi apagado voltar. Aconteceu três vezes em 15/08: apaguei 8 laudos de teste, conferi que tinham sumido, e minutos depois estavam de volta — sem erro nenhum na tela.
🔎 Por quê: ao salvar UM laudo, o app mandava pro servidor a lista inteira que ele tinha na memória. Se aquela lista era de antes da exclusão, o servidor recebia os apagados de volta e os regravava. Não tinha como escapar: pra apagar de verdade, todo mundo teria que fechar o app ao mesmo tempo.
✅ Agora o app manda só o laudo que mudou. Um laudo salvo mexe numa linha só: o que foi apagado continua apagado, e o laudo de outro laudista nunca é reescrito por quem não estava mexendo nele. Medido no app: ele tinha 9 laudos na memória e enviou 1.
👀 E a exclusão agora aparece na tela dos outros. O app perguntava ao servidor "mudou alguma coisa?" olhando só a data da última alteração — e apagar um registro antigo não muda essa data. Então quem estava com o app aberto continuava vendo um laudo que já não existia. Agora ele também compara quantos existem, então some da tela de todo mundo em poucos segundos.
🛡️ Vale para todas as listas que funcionam assim, não só a de laudos.
🔌 "Sem conexão" ao lançar retorno — com a internet perfeita. Tentar salvar um retorno na Escala dava sempre "Sem conexão — tenta de novo". Não era a internet: a tela de retorno nunca gravou desde que o sistema saiu do Firebase. Ela pedia gravação por um caminho antigo que só existe no modo Firebase e que, no PostgreSQL, fica vazio — então toda tentativa voltava como se fosse falta de rede. Isso explica os zero retornos cadastrados desde que o recurso nasceu, em junho: ele estava lá, ninguém tinha tentado usar até agora.
✅ Agora a Escala fala com o servidor pelo mesmo caminho que o resto do sistema usa. Criar, editar, remover e ver os retornos ao vivo — os quatro voltaram a funcionar, testados de ponta a ponta no navegador: criou, leu de volta com peso e paletes, editou, e removeu.
🛡️ Cada retorno continua sendo gravado sozinho, sem tocar nos outros — a proteção que evita um app apagar o que o outro acabou de salvar.
🔍 De onde veio o engano: o primeiro conserto que escrevi também estava errado (apoiava num atalho que o painel central não carrega). Só apareceu porque desta vez o teste foi feito no navegador, e não só na lógica.
📄 O expedidor agora manda o romaneio em PDF pelo celular dele. Ao finalizar a carga, o app da Expedição já prepara o romaneio sozinho e aparece um botão por cliente — um toque e ele manda pro faturamento no WhatsApp, no e-mail, no que preferir. Antes o papel só existia aqui no sistema: quem estava na doca não tinha como emitir.
🔢 O número é o mesmo contador de sempre, lido do servidor na hora de emitir — o romaneio do app e o do sistema nunca repetem número. E se o celular estiver sem conexão, o app não inventa número: avisa que o romaneio precisa sair pelo sistema. Número repetido no papel do cliente é pior do que emitir pelo computador.
🧾 Um romaneio por cliente, como no sistema (o papel é do cliente e o canhoto é dele). Tudo o que o app emite fica no Histórico de Romaneios daqui, com 2ª via.
♻️ Fechar a mesma carga de novo não gera número novo — sai o mesmo romaneio, com a mesma data. E se você mandar imprimir aqui no sistema uma carga que o app já emitiu, o sistema avisa e oferece a 2ª via, em vez de criar um segundo número pra mesma entrega.
🧩 Por baixo, o romaneio virou um documento só pros dois lugares — o mesmo caminho do laudo. Duas cópias do mesmo papel viram dois papéis diferentes com o tempo.
💵 O romaneio agora libera o pedido pro faturamento. Na tela Baixa, quem já tem romaneio aparece em primeiro, marcado "🧾 Romaneio Nº 14 — liberado pro faturamento", e a quantidade que aparece é a do romaneio (o que embarcou de verdade), não a produzida. Na hora de dar baixa, o número do romaneio vem escrito na pergunta.
🚚 Pedido que saiu em dois caminhões soma os dois romaneios e mostra os dois números. Reimprimir a 2ª via não conta duas vezes — a mesma carga embarcou uma vez só.
👀 Quem não passou por romaneio continua na lista, marcado "sem romaneio emitido". A fila não esconde ninguém: só põe na frente o que já está pronto pra virar nota.
🔗 A ligação é pelo pedido do palete, nunca pelo número do pedido (o mesmo número se repete em datas diferentes, e casar por ele marcaria o pedido errado). E nada disso é gravado no pedido: sai do próprio histórico de romaneios, então acompanha sozinho quando o romaneio chega do celular do conferente.
⚖️ Caixa com o mesmo código em clientes diferentes não confunde mais o peso. Existem 6 códigos repetidos entre clientes (CX 01, CX 02, CX 07, CX 09, CX 10 e 19403); quando a caixa não estava cadastrada naquele cliente, o romaneio pegava a medida e o peso de outro cliente — e esse peso entrava no total da carga e ia no WhatsApp do motorista. Agora só casa dentro do mesmo cliente: não achou, sai "—" e sem peso, que é um pedido de cadastro, não um número errado.
🚚 "Entregas ao vivo" ficava vazia à noite — e o caminhão estava na estrada. Depois das 21h a tela abria já marcando o dia seguinte e dizia "Nenhuma viagem com motorista nesta data". Ontem às 21:26 o Reinaldo já tinha marcado no app dele "saí da fábrica 21:25" e "cheguei no destino 21:26" — estava tudo salvo no servidor, a tela é que estava procurando no dia errado.
🕘 Por quê: a tela pegava a data pelo relógio de Londres (UTC), e aqui são 3 horas a menos — das 21h em diante lá já é amanhã. O app do motorista sempre usou o relógio da parede; agora a tela usa o mesmo, então os dois combinam.
🔔 O contador da aba também (o número verde ao lado de "Entregas ao vivo") zerava pelo mesmo motivo depois das 21h.
ℹ️ Nada mudou no app do motorista e nada foi perdido: as marcações daquela noite aparecem escolhendo o dia certo na tela.
🔄 Retorno e coleta viraram duas coisas diferentes — porque são. A tela chamava de "retorno" uma ficha cujos campos são de coleta (o quê · onde · destino Almoxarifado): balde de tinta, graxa, clichê. Só que retorno de verdade é CARGA — cimento, bobina — e muda uma coisa que a coleta não muda: ocupa o caminhão. Agora a ficha tem tipo, e o retorno pede peso e paletes, que aparecem pra quem monta a carga e pro motorista.
🛒 A Compra agora lança a retirada. Quem faz a compra é quem sabe que o material precisa ser buscado — antes isso só nascia dentro da Escala, então dependia do comprador lembrar de avisar alguém, e o pedido morria na conversa. No app de compras, na ordem já comprada, tem o botão "🔄 Precisa retirar", que já vem com o fornecedor e o material preenchidos.
📌 A Escala é quem pendura na viagem. A retirada nasce sem viagem — quem sabe quem vai pra aquela região é a Escala, não o comprador. Ela cai numa fila "Retiradas esperando viagem" no alto da tela de Escala, e lá se escolhe o motorista. Essa fila aparece até em dia sem viagem nenhuma: se ficasse escondida num dia vazio, o comprador lançaria e ninguém veria.
🏪 "Onde retirar" agora sai do cadastro de fornecedores — escolhendo, o endereço vai junto e o motorista ganha a rota. Quem não é fornecedor cadastrado (a fábrica de cimento) continua podendo ser escrito à mão, senão travaria justamente o caso que motivou tudo isso.
🚛 No app do motorista, retorno de carga aparece em laranja com o peso, e coleta de produto em roxo — ele sabe antes de sair se vai carregar peso na volta.
🛡️ Retorno antigo continua igual: ficha sem o campo novo é lida como coleta, que é o que ela sempre foi. Nada foi renomeado nem removido.
🚛 App do Motorista: três abas. Era uma tela só, e o que ele já tinha entregue continuava nela — o motorista terminava o dia com a tela cheia de coisa feita, caçando no meio o que ainda faltava.
🚚 Entregar — só o que falta. Confirmou a entrega, sai daqui na hora.
✅ Entregues — o histórico, com o dia e a hora de cada entrega. É onde ele prova o que já fez.
📅 Escala — as próximas viagens, não só a de hoje. Antes o app mostrava só o dia corrente, então ele não tinha como saber se estava escalado pra amanhã. Agora vê o dia, a hora de saída, o caminhão, o destino com a cidade e o botão de rota.
🔄 "Tem retorno?" agora tem resposta. Quando a viagem não tinha coleta, o bloco simplesmente não aparecia — e não aparecer nada é ambíguo: o motorista não sabia se era "volta vazio" ou se o app não tinha carregado. Agora está escrito: "Sem retorno nesta viagem — volta vazio". Quando tem, ele vê o quê e onde já na aba Escala, e os botões de confirmar continuam na aba Entregar, no dia.
🔖 A aba escolhida fica guardada no aparelho — esta tela se redesenha sozinha a cada aviso que chega, e sem isso ele perderia o lugar toda hora.
📄 O laudo do cliente agora sai numa folha A4 só. Ele estava saindo em duas páginas, e a segunda levava só o fim das fotos, o resultado (aprovado / não-conforme) e as assinaturas — o papel que vai pro cliente partido no meio. Agora cabe tudo numa folha: Dados do pedido e Especificação da caixa ficam lado a lado, e os espaços entre os quadros foram apertados. Nada foi tirado do laudo — as mesmas informações, as mesmas fotos, o mesmo resultado.
🔍 Laudo mais cheio encolhe sozinho pra continuar numa folha. Quando tem muita coisa (vários testes, mais de uma nota fiscal, observação comprida), o documento diminui de tamanho o quanto precisar pra caber — até um limite, porque papel ilegível não serve pra nada. Testado com 5 testes + 3 notas + observação longa: uma folha, tudo legível.
📱 O PDF do app da Qualidade não depende mais do aparelho. O PDF era montado do tamanho da tela de quem estava gerando: no celular o mesmo laudo virava mais páginas que no computador. Agora ele é sempre montado no tamanho da folha A4 — o laudo sai igual no celular, no tablet e no computador.
🖨️ O botão 🖨️ Imprimir do app da Qualidade passou a usar o mesmo documento do sistema central. Eram dois caminhos diferentes pro mesmo papel.
🚫 A tela de login estava CRIANDO usuário — acabou. Quem digitasse um nome que não existe (um nome errado, por exemplo) era cadastrado na hora como Visualizador, e o sistema ainda pedia pra pessoa escolher uma senha. Foi assim que nasceu o acesso "eliana.r", que ninguém pediu: ela errou o próprio nome e ganhou uma conta. Agora nome errado é só nome errado: a tela responde "Usuário ou senha incorretos" e nada é criado. A mesma resposta vale pra senha errada — de fora ninguém descobre quem existe e quem não existe.
👑 Criar acesso é só do admin principal, na tela de Usuários. Eram três portas criando gente sem ninguém pedir (a tela de login, a de "definir senha" e a que resolve o perfil); as três foram fechadas. Quem já está cadastrado entra igual, e quem foi cadastrado sem senha continua definindo a dele no primeiro acesso.
🪪 Agora o sistema pergunta ao SERVIDOR quem é você — o navegador não decide mais nada. Até aqui o seu nome e o seu perfil (Admin, PCP, Visualizador…) ficavam guardados dentro do navegador, e o sistema acreditava neles: quem soubesse mexer ali virava Admin sozinho e via as telas de todo mundo. Agora o servidor entrega um crachá no login, e a cada abertura o sistema pergunta "quem sou eu?". Vale o que o servidor responde. Mudou o perfil de alguém? Entra em vigor em até 5 minutos, sem a pessoa precisar fazer nada. Removeu o acesso? Ela cai na hora, mesmo com o sistema aberto.
🔒 E as rotas de acesso agora conferem quem está chamando. Criar usuário, mudar perfil e remover acesso só passam se quem pediu for o admin principal — antes essa regra existia só na tela (o botão sumia pros outros, mas o pedido era aceito por baixo).
📡 Servidor fora do ar = ninguém entra (decisão sua). A tela explica e oferece "tente de novo"; são 3 tentativas antes de desistir, pra oscilação de internet não fechar a porta na cara de quem está trabalhando.
⏱️ Duas horas parado, o sistema fecha sozinho. Computador esquecido aberto não continua dentro: a sessão é encerrada na tela e no servidor, e volta o login com o aviso "Sessão encerrada: 2 horas sem uso". Vale também pra quem reabre a página no dia seguinte. Qualquer clique, tecla ou toque zera o relógio — quem está trabalhando não é incomodado. O app do operador não entra nessa regra (tablet de máquina fica horas parado com produção aberta).
🔑 Trocou a senha, os outros aparelhos caem — só continua dentro o que você está usando na hora.
🧹 O acesso eliana.r que apareceu por engano pode ser removido na tela de Usuários, no botão 🚫.
🚚 O pedido carregado ficava preso em "Pronto p/ carregar". O caminhão saía com tudo, os paletes baixavam do estoque, a carteira até escrevia "saiu tudo (3 paletes)" — e o status não andava. Apanhado no teste de 15/08.
🔎 Por quê: a promoção pra "Carregado" era uma tentativa única. Ela acontecia no instante em que a caixa saía do estoque; se naquele momento o operador ainda estivesse com a etapa aberta, o pedido entrava numa fila de espera que só existia na memória do navegador — e essa fila morre quando a página é recarregada. Pior: depois que a caixa sai do estoque, a rotina que varre o estoque não passa mais por aquele pedido. Ninguém tentava de novo. Nunca mais.
⛓️ E isso quebrava a corrente inteira, calada: como a confirmação do motorista só transforma Carregado → Entregue, um pedido preso em "Pronto p/ carregar" também nunca chegava a Entregue, por mais que o motorista confirmasse.
✅ Agora existe uma varredura que não depende de memória: a cada 30 segundos o sistema relê o livro de saídas e, se tudo o que foi produzido já saiu em carga, marca Carregado — mesmo que o escritório estivesse fechado na hora do carregamento.
🛡️ O que continua igual: baixa manual do estoque não promove nada (só carga bipada, a regra que evitou 7 pedidos virarem "Carregado" por uma limpeza de PA); pedido com o operador ainda apontando espera; e carregamento parcial não vira "Carregado" — enquanto sobrar caixa na fábrica, ele continua esperando o resto.
🔬 App da Qualidade: três coisas.
🧹 Só entra o que já foi programado. O app recebia os pedidos que ainda estão esperando programação, escondia todos eles na hora de desenhar a tela, e ainda assim os contava lá em cima: dizia "81 pedidos" numa lista que mostrava 39. Agora o escritório nem manda esses — o celular do laudista baixa metade do peso e o número do topo passa a ser o que está na tela. Quem ainda não entrou na programação não é trabalho da Qualidade.
📚 Histórico de todos os laudos (aba nova). Antes a aba "Laudado" olhava a fila de pedidos — e no dia em que a mercadoria era entregue o pedido saía da fila levando o laudo junto: o documento que viajou com a carga sumia do app. Quem precisasse da 2ª via de um laudo do mês passado não tinha por onde. O Histórico lista os laudos pela lista de laudos, não pela fila, então laudo nenhum some mais. Tem busca por cliente, caixa, nº do pedido e número da nota, filtro por período, e mostra data, laudista, NF, quantidade e o veredito. Clicando, abre o mesmo laudo de sempre pra imprimir ou mandar de novo.
🚚 O caminhão saía e a Qualidade não ficava sabendo. A nota do laudo leva a quantidade do romaneio, então o app da Qualidade precisa saber o que embarcou. Só que essa conta era refeita apenas quando o escritório salvava a carteira de pedidos — e terminar um carregamento na Expedição não salva carteira nenhuma. Resultado: o caminhão ia embora e o laudista continuava vendo "este pedido ainda não foi carregado" por tempo indeterminado, justamente na hora em que ele precisa do número. Apanhado no teste de 15/08: carga fechada às 22:11 e a Qualidade parada nas 22:09, marcando zero caixa carregada com a mercadoria já na estrada. Agora, assim que uma carga muda, a conta é refeita e a Qualidade recebe na hora. É o mesmo remédio do aviso do motorista (v2.37.372): quando uma coisa depende de dois lados, ela tem que acontecer quando qualquer um dos dois chega. Carga ainda sendo montada continua não virando quantidade de nota.
💬 Dois avisos que se contradiziam. Na tela do pedido aparecia "produção finalizada · liberado pro laudo" e, dois cliques depois, na hora de emitir a nota: "este pedido ainda não foi carregado". As duas frases estavam certas, mas juntas pareciam que o sistema não sabia o que queria. O que a produção pronta libera são os testes (coluna e gramatura); a nota é que acompanha a mercadoria e espera o caminhão. Agora a primeira frase diz isso: "produção finalizada · já dá pra fazer os testes".
🖱️ A roda do mouse voltou a rolar a tela no computador. Depois da v2.37.352 (a que deixou puxar a tabela pro lado), no Mac a roda do mouse e o trackpad pararam de descer a página no app da Qualidade e no app do Operador. Só andava com o ponteiro em cima da barrinha de rolagem, na beirada da tela. No celular estava tudo normal.
🔎 O motivo: aquele arquivo novo passou a "escutar a roda" da página inteira, pra fazer o Shift + roda andar de lado. Só de escutar desse jeito, o navegador é obrigado a mandar cada giro da roda pro sistema antes de rolar — e o Safari, se o app estiver ocupado naquele instante, desiste da rolagem em vez de rolar depois. Em cima da barrinha a roda não passa por esse caminho: por isso ali continuava funcionando.
✅ Agora ele não encosta mais na roda. O arrastar a tabela pro lado com o botão do mouse continua igual, no PCP e em todos os painéis. E o Shift + roda também continua andando de lado — quem faz isso é o próprio navegador, não precisava do nosso código.
📱 De quebra, o toque no tablet ficou mais leve: tiramos outro trecho do mesmo tipo que atrapalhava o dedo no caminho rápido da rolagem.
🚚 A confirmação do motorista podia se perder no caminho. Quando ele toca em "entreguei" no app, o escritório lê isso e marca o pedido como Entregue. Só que essa leitura só acontecia no instante em que o aviso do motorista chegava. Se ele confirmasse à noite e o sistema fosse aberto de manhã, o aviso do celular dele podia chegar antes da carteira de pedidos terminar de carregar — e aí não havia pedido nenhum pra marcar. O aviso passava, não voltava mais, e o pedido ficava "Carregado" para sempre, sem ninguém desconfiar: o motorista já tinha feito a parte dele.
✅ Agora a leitura também acontece quando a carteira chega, fechando os dois lados. Se não houver nada pendente, ela sai na hora — não pesa nada.
👀 E o recado que morria no console agora aparece na tela. Quando o motorista confirma a entrega de um pedido que não está como "Carregado", o sistema continua não marcando sozinho (promover às cegas foi o que já marcou 41 pedidos como "em rota" por engano) — mas agora avisa: "Fulano confirmou a entrega de tal cliente, mas o pedido está como Em produção — não marquei Entregue sozinho. Confira." Antes esse recado ia pro console do navegador, que ninguém abre.
📦 Entrega parcial continua protegida: se ainda tem palete daquele pedido no estoque, o sistema avisa e não dá o pedido por entregue.
🔁 O aviso aparece uma vez por confirmação, não a cada atualização da tela.
👻 Caixa de pedido excluído ficava no estoque pra sempre — e ninguém via. Quando um pedido é apagado, a linha dele no Estoque PA continua lá, contando caixa que não existe mais. O ♻️ Recalcular nunca consertou essas: ele pula de propósito toda linha cujo pedido não está na tela (proteção que impede o estoque de zerar quando a lista chega pela metade). O resultado é que a linha nunca mais era conferida por ninguém. Caso real: FK GRUPO 35597, 1.670 caixas / 13 paletes, R$ 21.357,63.
🔎 Botão novo no Estoque: "Conferir órfãs". Ele junta as caixas cujo pedido não está na tela e pergunta uma por uma ao servidor. Só quem o servidor responder que não existe mais é apontado como órfã.
🛡️ "Não está na tela" não é "foi excluído" — e isso importa. Pedido antigo, já entregue, muitas vezes não está carregado; se o app decidisse pela ausência, apagaria estoque bom. Por isso a resposta do servidor manda: existe = nada a fazer; servidor fora do ar = dúvida, e dúvida nunca vira órfã.
🔒 Nada é apagado sozinho. A conferência só mostra. Tirar do estoque é um clique por linha, com uma pergunta que diz a quantidade, os paletes e o valor — e fica registrado no histórico de movimentos. Se as caixas existem no galpão, o certo é recriar o pedido, não apagar a linha; o aviso na tela diz isso.
♻️ O ♻️ Recalcular continua exatamente como era — a proteção dele não foi mexida.
🔢 A compra agora segue a ordem certa. Até aqui nenhuma etapa conferia a anterior: dava pra marcar uma peça como recebida sem nunca ter sido comprada, ou entregue sem ter chegado. Passava sem um aviso. Com o estoque ligado (versão anterior), um pulo desses somava ou tirava peça de um pedido que nunca passou pela compra.
✅ O caminho é: solicitada → esperando compra → comprada → recebida → entregue. Quem pular etapa recebe um aviso em português dizendo onde o pedido está e de onde aquela etapa pode ser feita — por exemplo: "Esta solicitação está solicitada — a etapa recebida só vale a partir de: comprada."
↩️ Devolver pra correção e cancelar continuam livres, como sempre foram: mandar pra revisão vale enquanto o pedido está aberto, e cancelar também.
🤝 A entrega direta do almoxarifado não mudou — quando a peça já está na prateleira, o almoxarife entrega na hora, sem passar por compra nenhuma.
🔧 Precisa do Luan (reiniciar o servidor) — é mudança na API.
📦 O estoque de peças passou a existir de verdade. Até agora, quando a peça comprada chegava do fornecedor, marcar "Recebida" só trocava o status — o saldo não subia. Alguém tinha que lançar a entrada na mão, sem nenhum vínculo com a compra; esquecer significava estoque a menos, lançar duas vezes significava estoque a mais. É por isso que as 11 peças do catálogo estavam todas sem saldo.
↔️ Agora o ciclo fecha sozinho: "Recebida" entra no estoque e "Entregue ao solicitante" baixa — cada uma gerando seu movimento no extrato, com quem fez e de qual solicitação veio. Quem quiser conferir, o histórico mostra o saldo depois de cada passo.
🔒 Clicar "Recebida" duas vezes não credita duas vezes — o sistema recusa a segunda e explica. E a entrega continua barrada em pedido já entregue.
🤝 A entrega direta do almoxarifado continua igual (quando a peça já está na prateleira, sem compra) — aquele caminho já baixava certo e não foi tocado.
⚠️ Entregar sem ter recebido deixa o saldo negativo, de propósito. Negativo quer dizer "saiu peça que o sistema não tinha" — é o sinal de que faltou registrar alguma entrada, e escondê-lo só empurraria o problema. Item fora do catálogo (sem cadastro) não tem saldo e segue sem mexer em nada.
🔧 Precisa do Luan (reiniciar o servidor) — é mudança na API.
📷 A foto do teste passou a ser tirada NA HORA DO TESTE. Antes as três fotos só eram pedidas lá na frente, na tela de emitir a nota: o laudista fazia os testes, guardava a chapa, e só descobria que faltava foto quando ia fechar o laudo — aí a foto já não era mais do teste. Agora a câmera está dentro da tela de Adicionar teste.
1️⃣2️⃣3️⃣ São 3 testes e 3 fotos, uma por teste: o 1º teste pede a foto do teste de coluna, o 2º a do teste de gramatura e o 3º a do painel. A foto da vez aparece destacada em azul; as outras ficam do lado, à mão.
⚠️ Salvar o teste sem a foto avisa, mas não trava — câmera que não abre ou celular sem espaço não podem impedir de registrar a medição, que é o que mais importa. A trava firme continua onde sempre esteve: sem as 3 fotos o laudo não é emitido.
🔔 O laudista agora é avisado — e o aviso não some. Antes era um recadinho que aparecia e sumia: quem não estivesse olhando a tela naquele segundo nunca ficava sabendo. Agora tem um quadro de avisos no alto da lista, que fica lá até ele ver, com três momentos:
🆕 entrou na programação — já dá pra fazer os testes de coluna e gramatura
✅ produção finalizada — a caixa ficou pronta
🚚 carregou o caminhão — "carregou 4.000 cx, falta o laudo desta nota"
👆 É só tocar no aviso que abre o pedido; ou "já vi todos" pra limpar a lista. Cada laudista tem a sua caixa de avisos, e a primeira vez que o app abre não despeja toda a notícia velha de uma vez.
🚚 O segundo caminhão também avisa. Um pedido que sai em duas entregas gera dois avisos — um por carga —, cada um dizendo quantas caixas embarcaram e estão esperando nota.
📊 Relatório por caminhão e por motorista. Tela nova em Expedição ▸ 📊 Por Caminhão/Motorista: escolhe o período e vê, de um lado cada placa e do outro cada motorista, com viagens, paletes, caixas, peso, tempo médio de carregamento e a data da última viagem.
🚛 No caminhão tem a ocupação — quanto do caminhão foi usado, em média. Ela só aparece pra caminhão com a capacidade preenchida no cadastro; hoje nenhum tem, então a coluna vem vazia até você preencher.
👤 No motorista tem as entregas que ele marcou no app, no mesmo período.
🧮 O relatório não inventa média: carga sem peso lançado fica de fora da conta de peso (não vira zero puxando a média pra baixo) e o total avisa quantas foram. Carga que ficou aberta por dias também não entra no tempo médio — seria "tempo de carregamento" de mentira.
🔤 Placa escrita de jeito diferente não vira duas linhas: "MAY 1542", "MAY-1542" e "may1542" são o mesmo caminhão.
📅 Só entram carregamentos finalizados; o que está em andamento não conta. O relatório enche sozinho conforme a Expedição vai fechando as cargas.
🚚 A nota do laudo agora sai com a quantidade do ROMANEIO. O laudo acompanha a mercadoria que embarca, não a que a fábrica produziu — mas o app da Qualidade nem enxergava as cargas: sugeria tudo o que tinha sido produzido, e o laudista tinha que descobrir na mão quanto o caminhão levou.
📦 Agora o app mostra o que já embarcou (data, placa, paletes e caixas de cada carga) e já sugere esse número na nota. Levou 4.000 de 6.000? A nota vem 4.000 e o laudo fica parcial, com o saldo esperando o próximo caminhão — que sai em outra nota, como já acontece na entrega parcelada.
⚠️ Três avisos novos, nenhum deles trava (decisão sua): produção ainda não finalizada; pedido ainda não carregado; e quantidade maior do que o caminhão levou. Se a carga não estiver no sistema — caminhão de terceiro, carga montada na mão — a Qualidade não fica presa: avisa, você confirma e a nota sai.
🧮 A conta é a mesma do romaneio (soma as caixas dos paletes daquele caminhão). Se um dia divergisse, o laudo e o papel que viaja junto com a carga estariam brigando na mão do cliente.
📄 O laudo do sistema agora é o MESMO papel do app da Qualidade. Eram dois documentos diferentes pro mesmo pedido: o do app tinha medida, onda, cor, especificado × encontrado, as fotos dos testes e o veredito; o que saía aqui do sistema era uma listinha com cliente, testes e notas — sem dizer se a caixa passou ou não. Agora os dois desenham o mesmo laudo, com tudo, pronto pra imprimir e mandar pro cliente.
🪪 E ele entrou na Vida da caixa. Uma estação nova 🔬 Qualidade · Laudo mostra o veredito, quem laudou, os testes, a gramatura, a coluna e a nota fiscal — com o botão 🖨️ Ver / imprimir o laudo ali mesmo. Antes era preciso sair da Vida da caixa e procurar em outra tela.
⚖️ A régua do veredito passou a existir num lugar só (gramatura ±5%; coluna acima da especificação aprova, porque é resistência mínima). Duas contas separadas era a fábrica aprovar num app e reprovar no outro — no papel que vai pro cliente.
🔬 O app da Qualidade mostrava três vezes mais caixa do que a fábrica produziu. No pedido 23532 da ALPACK, o quadro "Produção (do operador)" dizia 17.498 cx — e o pedido inteiro é de 6.000. O card verde logo acima, esse sim, mostrava o certo: 5.998 cx. Dois números diferentes na mesma tela.
🧮 Por quê: ele estava somando tudo o que passou pela caixa — as 6.000 da Slotter, as 5.998 da Coladeira e ainda 5.500 de um registro arquivado do dia 07/08. Só que a mesma caixa passa por mais de uma máquina: caixa pronta é a da última máquina, a que fecha. Contar as outras é contar a mesma caixa duas e três vezes.
✅ Agora o quadro mostra a caixa pronta de verdade — a mesma conta da Carteira: só a máquina de fechamento (Coladeira, Grampeadeira, Corte e Vinco, Facão), e registro arquivado não entra. Os dois números da tela passam a bater.
🧾 Isso também protegia a nota. Quando a etapa final ainda está zerada (a caixa foi cortada mas não colada), o app podia oferecer a quantidade da Slotter pra emitir a nota — caixa que ainda não existe pronta. Agora, nesse caso, ele mostra zero.
📦 Os paletes já estavam certos e continuam iguais.
🗺️ O motorista agora segue a viagem inteira no Maps, num toque. No alto do card da viagem tem o botão "🗺️ Seguir a rota — N paradas": abre o Google Maps já com todos os destinos na ordem da escala. Antes ele tinha que abrir um destino, entregar, voltar no app e abrir o próximo.
✅ Quem já foi entregue sai da rota sozinho. Entregou o primeiro cliente? Da próxima vez que ele tocar, o Maps já monta a rota só com o que falta.
🧭 O botão "Rota" de cada destino continua igual, com Google Maps e Waze — serve pra quando ele quer ir direto num cliente específico. A rota completa é só no Google Maps, porque o link do Waze aceita um destino de cada vez.
📍 Cliente sem endereço cadastrado fica de fora da rota (o sistema não tem pra onde mandar). Hoje 27 dos 35 clientes têm endereço — vale conferir os que faltam.
🕐 Previsão de chegada na escala. Depois que o motorista marca "Saí da fábrica", cada destino que ainda falta mostra a hora estimada: ALPACK 🕐 ~10:30. A conta é simples e de graça: hora real da saída + (km ÷ velocidade média) + tempo das paradas anteriores. Sem GPS, sem mapa, sem mensalidade.
🛣️ Onde entra a distância: no cadastro do cliente tem um campo novo, "Distância da fábrica (km)" — preenchido uma vez, pelo caminho que o caminhão realmente faz. Em Ajustes ▸ Configuração ficam a velocidade média (60 km/h) e os minutos por parada (30 min), que você ajusta pra realidade da sua estrada.
🚫 Cliente sem km cadastrado não mostra previsão nenhuma — e isso é de propósito. O pessoal da escala vai confiar nesse número, então é melhor vir vazio do que vir chutado.
✅ Destino já entregue mostra a hora REAL, nunca a estimativa. E toda previsão vem com o ~ na frente, avisando que é aproximada (sem contar trânsito nem tempo de descarga).
🔮 Deixei a origem da distância num lugar só no código: no dia em que a gente ligar um cálculo de rota de verdade, muda ali e a tela inteira acompanha.
🚚 "Saí da fábrica" — agora dá pra saber se o caminhão saiu mesmo. Até agora a escala só tinha a hora prevista, que o PCP digita quando monta a viagem; ninguém sabia se o motorista tinha realmente saído. O app do motorista ganhou o botão 🚚 Saí da fábrica, que carimba a hora real com um toque.
📋 A escala mostra o andamento da viagem. No card de cada viagem aparece agora: 🚚 Saiu 08:12 (previsto 08:00) · ✅ 2/3 entregues · 🏭 voltando. Quem ainda não saiu aparece em cinza; quem já passou da hora e não saiu aparece em âmbar — sem alarme, sem som, sem pop-up, é só informação pra quem olha.
🕐 A hora de cada entrega apareceu. Do lado de cada destino sai a hora que o motorista marcou (KININO ✅ 09:14). Esse dado já era gravado desde antes — só nunca tinha aparecido na tela da escala.
🔒 Desmarcar a saída pergunta antes, porque a hora real não volta. E marcar a saída não apaga o "voltando pra fábrica" nem as entregas já registradas — dois motoristas mexendo ao mesmo tempo continuam sem se atrapalhar.
👀 A tela Entregas ao vivo passou a contar pela mesma conta da escala, pra as duas nunca mostrarem números diferentes. Viagem antiga abre igual, só sem os dados novos.
🚛 Agora dá pra carregar caminhão de terceiro — e sai no romaneio igual ao nosso. Até agora a Expedição obrigava a escolher um motorista da nossa lista pra abrir a carga; pra carregar um terceiro tinha que escolher um motorista nosso qualquer só pra destravar, e aí o romaneio saía com o nome errado — justo o papel que acompanha a mercadoria.
🔀 Na abertura da carga tem dois botões: "Caminhão nosso" e "De terceiro". No modo terceiro você digita a transportadora, o motorista que veio buscar, o documento (CPF/RG), o telefone e a placa. Tudo isso sai impresso no romaneio, junto com a placa.
💾 O caminhão fica salvo pra próxima — o motorista não. É como funciona de verdade: a transportadora manda o mesmo caminhão, mas o motorista muda. Ao digitar uma placa já conhecida, o app preenche sozinho a transportadora e a capacidade, e ainda avisa quem veio da última vez. O nome de quem está levando você digita sempre — porque é ele que assina.
🖨️ A 2ª via sai igual à 1ª. Os campos novos entram no registro do romaneio, então reimprimir meses depois traz a transportadora e o documento do mesmo jeito.
✅ Caminhão nosso não mudou em nada — as linhas de transportadora e documento simplesmente não aparecem quando é da casa.
📤 O gêmeo da versão anterior — e este era pior. A v2.37.360 consertou o LER (a tela ficava em 0). Faltava o GRAVAR: no computador cujo navegador estava sem espaço, a sua alteração não chegava no servidor. Você trocava um status, a tela mudava, e a fábrica não recebia nada — sem erro, sem aviso.
🏭 E a publicação pro operador também não saía. Num caso o pedido até chegava no servidor, mas o app do operador não era avisado — ficava com a lista velha.
✅ Agora a cópia local nunca segura o envio. Se o navegador recusar guardar, o sistema manda pro servidor do mesmo jeito e avisa o operador normalmente. Vale pra pedidos, cadastros e os quadros de dados.
🔎 Como saber se o seu computador está assim: a barrinha lá em cima fica amarela dizendo "Sem espaço no navegador — limpe os dados do site". Enquanto ela estiver assim, limpe os dados do site naquele navegador.
🖥️ Achamos a causa do "Falhou ao atualizar" — aquele aviso que apareceu em UM computador só, com a carteira inteira em 0 enquanto no resto da fábrica estava tudo certo. A versão anterior ensinou o aviso a dizer o que falhou; esta conserta o que estava falhando.
🧯 O que era: o sistema guarda uma cópia dos pedidos dentro do navegador, e essa gravação vinha uma linha antes de desenhar a tela. Naquele computador o navegador estava sem espaço, a gravação estourava e o desenho nunca acontecia. Os pedidos chegavam do servidor — os 276 — e morriam ali. O F5 não resolvia: abria vazio, tentava, estourava, vazio de novo.
✅ Agora a cópia é só uma conveniência. Se o navegador recusar, a tela mostra os pedidos do mesmo jeito. A única diferença é que aquele computador rebaixa a lista toda vez que abre.
🗣️ E o aviso passa a dizer o que fazer: "Sem espaço no navegador — limpe os dados do site". Passando o mouse por cima, sai a explicação inteira.
🧩 Vale pra tudo que se sincroniza (pedidos, cadastros e os quadros de dados), não só pra carteira.
⚠️ A API nunca esteve fora nesse episódio — ela respondeu os 276 pedidos em meio segundo o tempo todo. O problema era só daquele navegador.
🧹 Os quatro últimos buracos da escala, fechados antes de ela entrar em uso:
👀 Agora dá pra ver o caminhão enchendo. A carga só existia no tablet até o "Finalizar": a escala ficava "⏳ Aguardando" o carregamento inteiro e pulava direto pra "🚚 Saiu" — ninguém no escritório via o progresso, e o motorista também não. Agora a carga aparece enquanto está sendo carregada (a lista sobe sozinha durante a bipagem, no máximo uma vez a cada 12 segundos pra não pesar).
➕ Segunda carga na mesma viagem. Depois de finalizar, o botão da viagem sumia e só sobrava o "Nova Carga" solto — que nasce sem o vínculo, então o motorista não era avisado da segunda leva. Agora tem "➕ Outra carga desta viagem", mantendo o elo.
🛑 Tocar no caminhão errado não apaga mais tudo no susto. O aviso dizia só "você tem uma carga em andamento" — agora diz de qual caminhão, de quais clientes e quantos paletes vão embora, e sugere finalizar a outra primeiro. Se for a mesma viagem, não descarta nada: continua de onde parou.
👥 Dois computadores montando a escala não se atropelam mais. O app gravava a lista inteira de viagens: se duas pessoas mexessem no mesmo dia, uma apagava a viagem da outra, sem erro na tela. Agora ele relê o servidor e mexe só na viagem em questão — preservando, inclusive, o que a Expedição já carimbou.
🔎 O aviso "⚠ Falhou ao atualizar — veja o console" passou a dizer O QUE aconteceu. Aquele avisinho no canto (embaixo do nome do sistema) é o sincronizador, que conversa com o servidor a cada 5 segundos. Quando ele tropeçava num caso não previsto, a frase só mandava "veja o console" — que é uma tela de programador que você não abre. Resultado: você ficou olhando pro aviso sem ter o que fazer, e quando eu fui procurar, a causa já tinha sido apagada pela tentativa seguinte. Agora o aviso mostra o erro de verdade, e passando o mouse por cima dele aparece a hora e o detalhe completo — dá pra tirar foto e me mandar.
🧭 Ele também separa "não recebi" de "recebi e não consegui usar". São problemas de origens opostas — um é servidor/internet, o outro é defeito no programa lendo os dados — e os dois davam a mesma frase. Agora aparece "⚠ Não consegui aplicar: …" no segundo caso.
✅ Conferi o servidor agora e ele está saudável (a lista de pedidos responde em 0,4 s, com os 276 pedidos certinhos). Ou seja: o que você viu hoje foi um tropeço passageiro ou um defeito ao aplicar os dados — e a próxima vez vai dizer o nome, em vez de sumir sem deixar rastro. Se aquele aviso vermelho aparecer de novo, é só me mandar a frase.
📱 O botão de avisar o motorista agora existe nos DOIS jeitos de carregar (começo do item nº 2 da pesquisa). Quem terminava pela aba "Carregar por Plano" voltava direto pra lista e nunca via o "Avisar Motorista" — ele só aparecia na carga montada pelo ▶ da escala. Agora os dois terminam na mesma tela de Carga Finalizada, com o botão do WhatsApp já com a mensagem pronta (placa, paletes, caixas, peso e os pedidos).
🙋 O botão agora chama o motorista pelo nome ("📱 Avisar REINALDO no WhatsApp"), e quando a carga saiu incompleta a tela mostra o motivo que o conferente escolheu.
🤐 Sem WhatsApp cadastrado, o botão some em vez de ficar prometendo o que não faz — e a tela avisa que é preciso falar com o motorista por outro caminho.
ℹ️ Por que WhatsApp e não notificação: a fábrica tem iPhone e Android. A notificação automática ainda não existe no sistema, e no iPhone ela exige que o motorista instale o app na tela de início — enquanto isso, o WhatsApp chega em qualquer celular, com o app fechado. É o aviso que funciona hoje.
📋 A conferência da carga agora fecha o ciclo — é o item nº 1 da pesquisa que fizemos sobre carregamento, e o que mais evita erro segundo os sistemas de armazém.
👀 Lista do que já entrou no caminhão. A tela mostrava só o placar por cliente ("2 de 3"); agora tem a lista palete por palete, o último em cima, com cliente, código, número do palete, pedido, hora e caixas — mais o total. É o que permite conferir de verdade e descobrir na hora se bipou algo errado.
⚠️ Fechar com palete faltando ficou um ato consciente. Antes era uma perguntinha seca ("faltam 3 paletes, finalizar mesmo assim?") — sem dizer de quem, e é a pergunta que todo mundo aceita no automático. Agora a tela lista cliente por cliente o que está faltando, o botão grande e verde é "↩ Voltar e bipar o que falta", e sair assim mesmo exige escolher um motivo (não coube, palete avariado, cliente pediu menos, vai em outra viagem, outro).
🧾 O motivo e a lista do que ficou viajam junto com a carga — o PCP passa a saber não só que saiu incompleto, mas por quê.
🚫 Não trava de propósito: carga parcial acontece de verdade. O que não podia é sair sem ninguém perceber nem saber o motivo.
↔️ O arrasto com o mouse chegou também no portal do cliente (o link que ele abre pra ver e aprovar a proposta). Numa tela estreita a nota do orçamento passava da largura e ele não conseguia ver as colunas da direita (preço, total) sem procurar a barrinha de rolagem — agora é só puxar de lado, igual no sistema e nos painéis (v2.37.352).
🎨 O visualizador da arte não mudou nada. Ali a arte já anda com o dedo/mouse por conta própria (arrastar move a folha, dois dedos dão zoom) — conferido que o arrasto novo não enxerga aquela área, então nada de duas mãos no mesmo desenho.
🛟 Tanto faz por qual tela o empilhadeirista bipar — agora as duas terminam igual. No app da Expedição existem dois jeitos de carregar: pelo ▶ da escala e pela aba "Carregar por Plano" (a que mostra o plano montado pelo PCP). Só o primeiro criava a carga. Quem bipava pelo plano via "🏁 Caminhão carregado!" e ia embora tranquilo, mas por fora não acontecia nada: nenhuma carga era criada, a escala não fechava, o motorista não era avisado e o romaneio não tinha de onde sair.
✅ Agora, ao concluir o plano, a carga nasce sozinha com os paletes bipados, encontra a viagem do dia daquele caminhão, fecha a escala e avisa o motorista — o mesmo que já acontecia pelo outro caminho.
💬 E a mensagem passou a dizer a verdade: "o motorista foi avisado" quando achou a viagem, "sem viagem de hoje pra este caminhão" quando não achou, e um aviso claro se a carga não subiu. Antes dizia sempre que tinha dado certo.
🔁 Concluir o mesmo plano duas vezes não cria carga repetida, e se o palete for de caixa sem peso cadastrado a carga já sai marcada como peso aproximado (igual à v2.37.350).
🚛 Preparação da ESCALA DE VIAGENS pra começar a rodar — três consertos no caminho "escala → carregamento → motorista":
🔤 Placa casa mesmo escrita diferente. O cadastro tem "CPN8C54" e a carga vinha "CPN 8C54" — só o espaço já fazia o sistema não reconhecer que era o mesmo caminhão. Conferi as placas reais: nenhuma das 6 usadas em carga casava com o cadastro. Agora espaço, traço e ponto são ignorados na comparação.
🏁 A escala fecha sozinha. Quando o conferente finaliza a carga, a viagem passa a "Em rota" automaticamente, com a hora e o nome de quem carregou. Antes ela ficava "Programada" pra sempre e só o rótulo da tela mudava — no dia seguinte a viagem de ontem aparecia como se não tivesse saído. Viagem já marcada como entregue ou cancelada não é tocada.
🔔 O aviso de carga pronta não se perde mais. Dois defeitos: o sino do app do motorista desligava sozinho a cada abertura (ele tinha que tocar toda vez, e quase nunca tocava), e se a carga ficasse pronta com o app fechado o aviso era descartado em silêncio — pra sempre. Agora o sino fica ligado, e a carga que ficou pronta vira uma faixa verde grande "🚚 CARGA PRONTA" que espera ele abrir o app, com a placa e a hora, até tocar em "Vi".
⚠️ Importante pra quem carrega: a carga precisa ser começada pelo botão ▶ da escala, não pelo "Nova Carga" — é o que amarra a carga à viagem do motorista.
↔️ Agora dá pra puxar a tabela pro lado com o mouse. Numa tela menor (1.200×800, por exemplo) as tabelas largas — a Carteira/PCP, a lista de Caixas e as outras — passam da largura do monitor, e as colunas da direita (quantidade, ✏️ editar, 🗑️ excluir) ficavam escondidas. Quem usa notebook desliza dois dedos no trackpad e no celular arrasta com o dedo; o mouse não tem esse movimento pro lado, então sobrava só a barrinha de rolagem — que fica no rodapé da lista, embaixo de centenas de linhas: era descer a página inteira, arrastar a barrinha e subir de volta. Agora é só segurar o botão do mouse em cima da tabela e puxar pro lado, igual arrastar um mapa. O cursor vira uma mãozinha nas tabelas que têm mais coisa pro lado.
🖱️ Segurando o Shift, a roda do mouse também rola de lado — pra quem preferir não tirar a mão da roda.
🔒 Nada do que já funcionava mudou. A roda sozinha continua rolando a página normalmente (de propósito: se ela virasse rolagem lateral, você ficaria preso na tabela e não desceria mais a página). Clique continua clique — o pedido só deixa de abrir quando você realmente puxou a tabela, não num clique parado. E o campo de quantidade e o seletor de status continuam funcionando igual: em cima deles o arrasto não pega. No celular e no tablet nada foi tocado.
📗 O papel virou UM livro só. Ele era contado em dois lugares — o estoque em quilos (que nascia da nota) e os rolos — e os dois discordavam em todas as linhas. A causa não era perda: era a largura. O estoque guardava a largura que vinha da nota, e pra DCX ela vinha zero; o rolo tem a largura real. Agora o saldo é por dono · papel · gramatura, e a largura vem dos rolos, onde ela é medida de verdade.
✅ A prova: o BARILE 220 da DCX estava numa linha só no livro e em dois grupos de rolos (1000 e 1040 mm). Com a largura fora da chave, ele passou a bater ao quilo: 14.632 kg no livro × 14.632 kg em rolos.
👀 Cada papel agora mostra as duas coisas na mesma linha: quanto o livro diz, quanto os rolos somam (com quantos rolos e quais larguras, e quantos estão na máquina) e a diferença. Onde falta acertar, o app diz o que a diferença significa — "papel que entrou sem nota" ou "papel lançado que não virou rolo" — e tem o botão acertar do lado.
📝 Acertar exige motivo. O ajuste vira um lançamento no extrato, com quem fez e o porquê. Saldo que muda sem explicação é saldo inventado.
🧮 Nada foi perdido na mudança: as linhas foram apenas somadas — 72.190 kg antes, 72.190 kg depois (testado com os dados reais da fábrica). "Jp" e "JP" viraram um dono só, e as APARAS continuam no livro (sucata não vira rolo, e saldo sem rolo é legítimo).
🔧 Precisa do Luan (atualizar o banco e reiniciar o servidor).
✅ Os dois últimos achados da auditoria do carregamento (os "leves") — com isso a varredura fica só com o que depende de decisão sua.
⚖️ Peso da carga: "0 kg" não passa mais por peso de verdade (nº 17). Palete de caixa sem peso cadastrado entrava na conta como zero, calado — duas das oito cargas do histórico saíram com 0 kg no resumo e na mensagem do motorista, parecendo peso real. Agora a tela mostra "≈ 96 kg" quando a soma está incompleta, avisa quantos paletes e quais caixas estão sem peso, e quando nenhuma tem peso escreve "peso não cadastrado". No WhatsApp do motorista, peso parcial vai com "≈" e a observação; sem peso nenhum, a linha simplesmente não sai — melhor não falar de peso do que mandar um número errado.
📝 Status em branco não é mais gravado no pedido (nº 18). A vida do pedido 23820 tinha a linha "Editado: status Pronto → ", com o destino vazio: a tela devolveu status em branco e o sistema gravava esse vazio no pedido — e como o servidor entende vazio como "não mexe", tela e banco ficavam diferentes sem ninguém ver. Agora o campo em branco é ignorado (fica o status que já estava) e o histórico registra que a mudança foi recusada, em vez de mentir.
📉 O estoque de papel agora DIMINUI. Ele nasceu só com entrada: crescia quando a nota era importada e nunca baixava — o número na tela era o total que já entrou, não o que ainda tem. Agora, quando um rolo é fechado no "🔙 Voltou da máquina", os quilos que a máquina comeu saem do estoque daquele dono. O peso usado é o REAL (o que entrou menos o toco pesado na balança), não uma estimativa.
🧾 Nasceu o extrato do papel: entradas e saídas na mesma lista, com quem fez, a nota de origem e o rolo que gerou cada baixa. Saldo que muda sem extrato é número que ninguém consegue conferir.
🔒 O mesmo rolo nunca baixa duas vezes. Cada saída carrega a origem dela, e o sistema recusa a segunda — testado com 6 aparelhos dando baixa do mesmo rolo ao mesmo tempo: entrou uma só.
⚠️ O saldo pode ficar negativo — e isso é de propósito. Negativo quer dizer "consumimos papel que nunca foi lançado por nota" (hoje as bobinas da DCX somam ~5,7 t a mais que as notas importadas). Esconder isso zerando por baixo tiraria da vista justamente o que precisa ser resolvido; quando acontece, o app avisa na hora.
🔧 Precisa do Luan (atualizar o banco e reiniciar o servidor). Até lá o fechamento do rolo continua funcionando normal — só a baixa em quilos fica esperando.
🧻 Receber bobina virou conferência de verdade. Até agora dava pra digitar qualquer número por cima da nota, sem uma pergunta. Agora o app compara o que foi digitado com o que a NF diz — gramatura, largura e peso — e, quando não bate, mostra a diferença e pede confirmação. Quem assume a divergência fica registrado no rolo.
⛔ Rolo sem gramatura não entra mais. Era o pior buraco: a gramatura é lida da descrição do produto da nota e, quando o fornecedor escreve diferente, vinha zero — aí o rolo entrava com 0 metros, a etiqueta saía "0 m" e, lá na frente, a onduladeira dava ✅ verde em qualquer bobina porque não tinha com o que comparar. Agora o app barra e explica; e quando a nota não traz a gramatura, avisa no alto do papel pra pegar na etiqueta do fornecedor.
👷 Ficou registrado quem recebeu. O sistema já sabia guardar isso, mas o app nunca mandava — todo rastro de entrada nasceu sem dono. Agora vai o nome de quem conferiu, e corrigir um rolo já conferido também deixa marca (antes a correção era invisível).
📦 Fechar recebimento com rolo faltando agora avisa ("chegaram, mas o sistema não vai saber que existem"), e a diferença de peso contra a nota — que era só uma cor na tela — passou a pedir confirmação quando passa de 2%.
🕐 A hora dos registros da expedição agora é a do SERVIDOR, não a do tablet (achado nº 14 da auditoria). Início e fim da carga, hora da bipagem e o "quando" de cada saída de palete vinham do relógio do aparelho — tablet com a hora errada carimbava a hora errada no livro de saídas, e ninguém tinha como saber depois. (Essa mesma família de problema já travou o sincronismo da fábrica uma vez, com um PC adiantado.)
🎁 Sem custo: toda resposta que o sistema recebe já traz a hora do servidor dentro dela. O sistema passou a ler essa hora e corrigir a diferença sozinho — não tem chamada extra nem nada pra configurar.
🛡️ Se a diferença for absurda (mais de 12 horas, cara de fuso horário errado ou dado bichado), o sistema ignora e continua com o relógio do aparelho — melhor a hora local do que um carimbo maluco. Hora de login e de sessão continuam sendo do aparelho de propósito: são dele, não do registro da fábrica.
🔗 A carga agora sabe de qual viagem ela é (achado nº 10 da auditoria). O sistema descobria isso por placa + dia — e errava de dois jeitos: a carga montada aqui no sistema nasce com a placa do cadastro do motorista (não a do caminhão da escala), então a viagem ficava "⏳ Aguardando" pra sempre; e duas viagens do mesmo caminhão no mesmo dia viravam uma só.
🎯 O app da Expedição já gravava o código da viagem em cada carga — só que ninguém lia. Agora é esse código que manda. Carga antiga, sem o código, continua sendo casada por placa e dia, como antes.
👥 Nome de cliente parecido não conta mais como igual. A conta de "todos os clientes já foram carregados" aceitava qualquer nome que contivesse o outro — "MILI" dava por carregada uma viagem da "MILI BEAUTY". Agora é nome exato (é a mesma família de erro que um dia marcou 41 pedidos da FK como "em rota").
ℹ️ Esses avisos só voltam a aparecer quando o módulo de Escala de viagens for usado de novo — ele está sem nenhuma viagem lançada desde 29/07.
👷 Encarregado e comprador também criam a própria senha no 1º acesso. Com estes dois, todos os apps que entram por senha de 4 dígitos passam a funcionar igual: conferente, laudista, manutentor, encarregado e comprador. A senha que o PCP digita é provisória — entra uma vez e o app pede uma nova, diferente da provisória, digitada duas vezes.
🙈 A senha sumiu das duas tabelas. Nos cadastros de Encarregados e Compradores ela ficava escrita na tela; agora mostra só 🔒 (criou a dele) ou 🔑 (ainda provisória). No editar o campo vem vazio: vazio = mantém a dele, digitar = vira provisória de novo (é assim que se reseta a senha de quem esqueceu).
🔒 Mesma trava dos outros: 5 senhas erradas seguidas e o app espera 1 minuto; a senha digitada não fica guardada na memória da tela depois que a pessoa entra.
📤 Dar saída acima do pedido agora AVISA (achado nº 6 da auditoria). A varredura achou 8 dos 15 pedidos com saída maior que a quantidade pedida — a PAPELARIA REVAL saiu com 11.073 de um pedido de 10.000, e um pedido da FK de 300 caixas saiu com 762 (mais que o dobro). Ninguém era avisado.
🧮 Agora, ao dar saída de palete no Estoque PA (um a um ou pelo botão 🚚), se a conta passar da meta o sistema mostra na hora: quanto era o pedido, quanto já saiu, quanto vai sair agora e quantas caixas a mais dá no total, com a porcentagem.
✅ Avisa, não barra — igual ao peso mínimo do orçamento. Mandar a mais pode ser de propósito (sobra de produção que o cliente aceita); o que não pode é ninguém ficar sabendo. Uma folga de 2% não incomoda, pra não avisar por causa de arredondamento de palete.
📱 Na bipagem do caminhão o aviso não aparece de propósito: o tablet trabalha com a lista que carregou no login e avisaria errado — conferente que recebe alerta falso para de ler alerta.
🔎 Bônus: o aviso "SEM CONEXÃO COM API" agora diz a causa. Ele aparecia para qualquer problema — token recusado, erro do servidor, API desatualizada, até falha ao aplicar os dados que chegaram — sempre culpando a internet. Agora a barra mostra o que realmente aconteceu ("API recusou o acesso", "Erro no servidor (502)", "Sem internet no aparelho", "Servidor fora do ar"), pra dar pra agir em vez de adivinhar.
🔧 Agora o manutentor também cria a própria senha no 1º acesso — o mesmo que já vale pro conferente da Expedição e pro laudista. A senha que o PCP digita no cadastro é provisória: entra uma vez e o app pede pra criar uma nova de 4 dígitos (diferente da provisória, digitada duas vezes).
🙈 A senha sumiu da tabela de manutentores. Ela ficava escrita na tela do sistema — agora aparece só quem já criou a dele (🔒) e quem ainda está com a provisória (🔑). No editar, o campo vem vazio: vazio = mantém a dele, digitar = vira provisória de novo (é assim que se reseta a senha de quem esqueceu).
🔒 Trava contra tentativa em série: depois de 5 senhas erradas seguidas o app de manutenção espera 1 minuto. E a senha digitada não fica mais guardada na memória da tela depois que ele entra.
📄 Romaneio: número que não repete e conferência de verdade (achado nº 12 da auditoria). Três coisas no papel que vai pro cliente:
🔢 O número era um contador de cada computador. Dois PCs emitindo davam o mesmo número de romaneio. Agora o número sai do maior já emitido, calculado na hora a partir do histórico que todos compartilham (mesma ideia da versão da arte no Desenvolvimento, que nunca usou contador guardado).
✍️ "Carregado por" e "Conferido por" saíam com o MESMO nome — quem carregou aparecia como se também tivesse conferido. Agora "Conferido por" sai em branco, pra assinar na mão: quem carrega não confere o próprio serviço.
🖨️ A 2ª via saía com data diferente da 1ª (mesmo número, data de hoje) — duas folhas divergentes na mão do cliente. Agora a reimpressão sai idêntica à original, com a data da emissão, e marcada como 2ª VIA.
🔑 Laudista agora cria a própria senha no 1º acesso — igual ao conferente da Expedição (v2.37.329). A senha que o PCP digita no cadastro virou provisória: serve pra entrar uma vez, e o app obriga a criar uma senha nova de 4 dígitos (diferente da provisória, digitada duas vezes). O PCP trocar a senha no sistema = reset: no próximo acesso ele cria outra.
🙈 A senha pessoal não aparece mais no sistema. A tabela de laudistas mostrava a senha escrita na tela — agora mostra só quem já criou a própria (🔒) e quem ainda está com a provisória (🔑). No editar, o campo vem vazio: vazio = mantém a dele, digitar = vira provisória de novo.
📵 A senha parou de ser guardada no aparelho. A sessão de 12 h gravava o laudista inteiro no celular, senha junto. Agora guarda só o nome e o código — a senha não fica registrada em lugar nenhum do aparelho.
🚫 Laudista inativo não entra mais. Quem estava marcado como inativo no cadastro continuava aparecendo na tela de login do app. Além disso, depois de 5 senhas erradas seguidas o app trava por 1 minuto — antes dava pra ficar tentando à vontade.
💾 Fechar a carga não sobrescreve mais o que os outros fizeram (achado nº 7 da auditoria — o primeiro dos "médios"). Eram dois vazamentos no mesmo botão:
🚚 Duas cargas fechadas quase juntas: a segunda apagava a primeira. O tablet gravava a lista de cargas que ele tinha na memória (atualizada a cada 4 segundos) por cima da do servidor. Agora ele relê o servidor na hora, acrescenta a carga dele e só então grava — e reenviar a mesma carga não duplica.
📋 A carteira INTEIRA subia junto, com a foto do login. O app do conferente lê os pedidos uma vez quando ele entra e a sessão dura até 12 horas; ao finalizar a carga, essa lista velha era gravada por cima de tudo — quantidade, valor, cliente, código, roteiro, observação e programação de todos os pedidos voltavam ao que eram de manhã. Agora sobem só os pedidos daquela carga (2 ou 3, em vez de 262), e só o status deles muda.
🚦 A bipagem do palete agora fala por COR (pedido do dono). O aviso grande na tela tem três caras, pra o conferente entender de longe, sem ler:
🟩 VERDE — "PALETE BIPADO": entrou na carga, tudo certo.
🟧 LARANJA — "JÁ FOI BIPADO": esse palete já tinha sido lido; não entra duas vezes.
🟥 VERMELHO — "FORA DO PLANEJAMENTO": o palete não é desta carga.
🔊 O som acompanha: bip curto e agudo no verde, dois bips graves no laranja e no vermelho — o conferente costuma estar de costas pro tablet empurrando palete, e a cor sozinha não alcança. O aviso de erro também fica mais tempo na tela (o vermelho, mais de 2 segundos).
🧻 A onduladeira passou a enxergar o rolo que já está montado na máquina. O desconto de metros existia desde a v2.31.99, mas só rodava se o operador digitasse o código do rolo em cada papel, em cada pedido, toda vez — e a memória disso era apagada a cada card. Resultado: 74 bobinas no sistema e nenhuma com consumo; 3 rolos estavam "na onduladeira" há mais de 40 dias com os metros cheios. Agora, quando a empilhadeira dá baixa do rolo pra Onduladeira, o app da onduladeira preenche o rolo sozinho no papel certo — o operador só confere o ✅.
🔕 Acabou o lançamento mudo. Lançar produção sem nenhum rolo identificado passava batido: a chapa entrava no sistema e o papel nunca saía do estoque, sem uma palavra na tela. Agora o app avisa antes ("o estoque de papel NÃO baixa e a perda deste pedido não vai existir") e deixa o operador decidir — e o resultado do lançamento diz, em amarelo, se o papel baixou ou não.
🎯 Só preenche quando tem certeza. Exige rolo com destino Onduladeira (os 23 rolos de "Limpeza de teste" ficam de fora), gramatura igual à da camada e largura compatível; se dois rolos servirem e a posição não desempatar, deixa em branco pro operador digitar. Chutar o rolo seria pior que não preencher — baixaria metros do rolo errado.
💰 Agora o senhor escolhe quem vê a comissão no App do Vendedor. No cadastro do vendedor (Logística ▸ Vendedores) apareceu um ✓ "Mostrar a aba Comissão no App do Vendedor". Desmarcou, aquele vendedor deixa de ver a aba 💰 Comissão no celular dele — e a % de comissão também some do cartão de cada cliente dentro do app (o número estava nos dois lugares; esconder só a aba não adiantaria nada).
👀 Na lista de vendedores tem uma coluna nova dizendo, de cara, quem ✅ vê e quem 🚫 não vê.
🔁 Vale na hora: o senhor marca ou desmarca aqui e o app dele muda sozinho no próximo carregamento, sem precisar sair e entrar de novo.
✅ Ninguém perde nada de surpresa: todo vendedor já cadastrado continua vendo a comissão como sempre viu — só deixa de ver quem o senhor desmarcar. O relatório de comissões aqui do PCP e o fechamento no Financeiro não mudam em nada.
🚚 O motorista agora marca ENTREGUE — e o pedido vira Entregue sozinho (fase 5, a última crítica da auditoria do carregamento). Antes o "✅ Entreguei" do app só desenhava na tela: o pedido só virava entregue quando alguém trocava o status na mão, aqui no escritório.
📱 No app do motorista nasceu "Minhas cargas". Toda carga finalizada com ele como motorista aparece por 7 dias, com um cartão por pedido (cliente, nº do pedido, código, paletes e caixas). Ele confirma pedido por pedido, conforme descarrega. Isso resolve também um problema antigo: a tela do motorista dependia da escala, e como não se monta escala desde julho, o app dele estava vazio — a carga é o que existe de verdade.
🎯 O vínculo é pelo NÚMERO INTERNO do pedido, não pelo nome do cliente — cada palete bipado já carrega o pedido dele, então não tem como confirmar a entrega de um e baixar outro (o erro que já marcou 41 pedidos errados no passado).
🛡️ Três cuidados, de propósito: o app do motorista não escreve na carteira (ele avisa, o escritório aplica); só vira Entregue o pedido que está Carregado — e se ainda sobrou palete no estoque, o sistema avisa que é entrega parcial e deixa a decisão com você; e a data que fica gravada é a de quando o motorista confirmou, não a do dia em que o escritório abriu o sistema.
🔒 Pedido que já saiu não pode mais ser excluído (fase 4 da auditoria do carregamento). A auditoria achou um pedido da FK apagado da carteira deixando 13 paletes / 1.670 caixas soltos no livro de saídas — mercadoria que saiu, pedido que sumiu, e nada pra confrontar com o faturamento.
🚫 Agora, tentar excluir um pedido que tem palete no livro de saídas ou que está numa carga finalizada é barrado, com o aviso dizendo quantos paletes e quantas caixas — e o que fazer se a exclusão for de verdade (estornar as saídas primeiro, no Estoque PA ▸ paletes ▸ ↩). Vale nos dois lugares onde dá pra excluir: o ✕ da lista e o botão dentro do pedido.
🛡️ A trava também foi pro servidor, não só na tela: mesmo que alguém tente por fora do sistema, o banco recusa. Pedido sem movimentação de expedição continua excluindo normal, indo pra 🗑️ Lixeira como sempre. É a mesma ideia da trava que já impede apagar cliente com pedido vinculado.
🧾 NF inventada não entra mais no laudo. Toda nota de laudo já emitida usava número de NF de mentira ("1234" em quatro laudos de clientes diferentes, "12345", "1230") — e esse número sai impresso no documento que vai pro cliente. Agora o app da Qualidade barra número que nenhuma NF real tem (sequência tipo 1234, dígito repetido tipo 1111, menos de 3 dígitos), pede confirmação com o número na cara quando ele é curto demais, e avisa quando a mesma NF já foi usada no laudo de outro cliente (uma NF é de um cliente só).
✍️ O campo parou de ensinar o vício: o exemplo dentro do campo era justamente "Ex: 12345" — e foi "12345" que acabou impresso num laudo. Virou "copie da nota fiscal", com o aviso de que o número sai no documento do cliente.
✍️ Toda saída de palete agora sai ASSINADA (fase 3 da auditoria do carregamento). A auditoria achou 141 das 186 saídas de estoque sem responsável — e a causa era um defeito bobo: o nome do usuário logado nunca chegava na baixa (a variável certa não era lida). Consertado: a baixa e o estorno gravam o nome de quem está logado no sistema.
🚫 Sem usuário identificado, a baixa NÃO passa. Dar saída, dar saída em tudo (botão 🚚) ou estornar palete sem login identificado agora é barrado com aviso — a movimentação de produto acabado precisa de dono. A confirmação mostra "Sai como: fulano" antes de gravar.
📜 As 141 saídas antigas continuam sem nome (histórico — não dá pra inventar autor); daqui pra frente fica tudo assinado.
🧪 O laudo agora tem veredito de verdade — gravado, não só desenhado. Ao emitir a nota, o app da Qualidade compara as medições com a especificação da caixa e grava o resultado no laudo: APROVADO, NÃO-CONFORMIDADE ou "sem referência". Antes o "aprovado" era só um desenho no PDF, recalculado a cada abertura — e caixa sem espec cadastrada saía "✓ PRODUTO APROVADO" sem ter sido comparada com nada. Agora esse caso avisa o laudista e o PDF sai como "medições registradas", sem selo.
🔔 Laudo fora da espec chega no sino do PCP. Se a medição sair fora, o laudista é avisado na hora, confirma que quer emitir mesmo assim, e o alerta 🧪 aparece no sino do sistema com os números (fica lá por 7 dias — ajustável no ⚙ do sino). Antes ninguém no PCP ficava sabendo: 4 dos 6 laudos da história saíram fora da tolerância, calados.
💪 Coluna acima da espec não reprova mais. A conta antiga era simétrica: uma caixa com coluna 5,4 numa espec de 4 (35% MAIS resistente que o pedido) saía como não-conformidade. Coluna é resistência mínima — agora só reprova abaixo da espec (com 5% de tolerância). A gramatura continua ±5% pros dois lados.
🧊 Laudo emitido não muda mais sozinho. A especificação usada na comparação fica congelada dentro do laudo — mexer no cadastro da caixa depois não reescreve o PDF de um laudo já entregue ao cliente. Laudo antigo (de antes desta versão) continua como era.
🚚 "Carregado" agora SÓ pela carga bipada (fase 2 da auditoria do carregamento — decisão do dono). A baixa manual de palete no Estoque PA tira do estoque, mas o pedido fica em "Pronto p/ carregar" até passar por uma carga/bipagem na Expedição. Antes, limpar o PA em lote marcava "Carregado" sem caminhão nenhum — em 13/08 foram 7 pedidos no mesmo minuto. Mudar o status na mão pela carteira continua funcionando.
📦 O botão 🚚 do Estoque PA mudou junto: dá saída em todos os paletes que restam (fica registrado no livro de saídas, com aviso honesto) — sem marcar "Carregado".
🔊 Bipou o palete → BIP de scanner + aviso GRANDE na tela (1 segundo): "✅ PALETE BIPADO", a quantidade bem grande e o cliente. Vale nos dois jeitos de bipar (Nova Carga e Carregar por Plano). O som destrava no primeiro toque na tela (jeito do iPad).
🧪 O laudo da Qualidade voltou a salvar — e não trava mais. Desde 24/07 nenhum laudo salvava e ninguém via erro: um laudo apontava um pedido que foi excluído, e como o app grava todos os laudos de uma vez, esse único laudo órfão derrubava a gravação de todos. O laudo foi consertado no banco (14/08) e agora a API foi blindada: pedido excluído não derruba mais a gravação — o vínculo fica vazio e os laudos salvam do mesmo jeito.
📡 Laudo editado agora aparece nos outros aparelhos. Antes só laudo NOVO avisava os outros aparelhos; nota nova, teste ou finalização num laudo já existente ficava invisível até recarregar na mão. Agora qualquer mexida no laudo atualiza o carimbo e os outros aparelhos recarregam sozinhos.
🔑 Conferente da Expedição: 1º acesso agora TROCA a senha. A senha que o PCP digita no cadastro virou provisória — serve pra entrar uma vez. No primeiro acesso o app pede pra criar uma senha nova de 4 dígitos (diferente da provisória, digitada duas vezes) e ela vira a senha pessoal dele. O PCP trocar a senha no sistema = reset: no próximo acesso o app obriga a criar outra.
🙈 A senha pessoal não aparece mais no sistema. O editar conferente vem com o campo vazio (vazio = mantém a senha dele; digitar = trocar). E a lista mostra quem já criou a própria senha (🔒) e quem ainda está com a provisória (🔑).
🐛 A tabela de conferentes aparecia VAZIA com "4 cadastrados" do lado. Um cache guardado no formato errado fazia a tela quebrar no meio, caladinha — o contador já tinha sido escrito e a tabela nunca era desenhada. Consertado: a lista aparece, com as cargas dos últimos 30 dias contadas do jeito certo.
🛡️ A Importar Relatório parou de mexer na quantidade de pedido que já saiu da fábrica. A auditoria do carregamento pegou o estrago: pedido ENTREGUE com sobra de chapa lançada era tratado pela importação como "esperando material" e tinha a quantidade reescrita dias depois da entrega (KININO caiu de 15.000 pra 2.513; TANGARA de 8.843 pra 376) — e a comissão do vendedor e os relatórios usam valor × quantidade.
🚚 Agora pedido Carregado ou Entregue é intocável pra importação na quantidade, cliente e código (data, valor e observação continuam atualizando, como sempre). O status Carregado também entrou na lista de protegidos — estava fora e um pedido carregado "cru" podia ser reescrito por inteiro.
✋ Ajuste de meta agora GRUDA. Quando o PCP ajusta a meta no reprogramar parcial (o restante vira pedido novo), a quantidade fica carimbada como decidida na mão — a importação não desfaz mais (foi o caso JESSE de 10/08: o PCP ajustou 15.000 → 10.773 às 15:27 e a importação desfez às 16:35, contando a mesma demanda duas vezes).
🔎 Nada muda pra pedido que ainda não saiu: relatório continua mandando na quantidade, data e preço como antes.
⏱ As máquinas cadastradas agora entram na telinha "⏱ Turnos" do cronograma. Antes, só as 4 de fábrica (Slotter, Corte e Vinco, Coladeira e Grampeadeira) apareciam ali — uma máquina criada no cadastro (Cabeçote, Facão, Integrada…) ganhava raia no cronograma, mas ficava presa no turno geral: não tinha como dizer o horário dela, e a raia mostrava "livre 17h36" com almoço em horário errado.
⚙️ Agora cada máquina cadastrada aparece na lista e pode ter turno próprio (início, horas, almoço), igual às de fábrica. Sem marcar nada, continua no turno geral — nada muda pra quem não mexer.
📺 O Mural e o app do operador passam a respeitar esse horário também (o fim de turno automático da máquina cadastrada fecha na hora certa dela, não na do turno geral).
📏 A régua do dia e a impressão do cronograma acompanham: se uma máquina cadastrada fechar mais tarde que as outras, o dia estica pra mostrar o turno dela inteiro.
⏰ O fim de turno agora PERGUNTA e COBRA a quantidade. 30 minutos antes do fim do turno da máquina, o app do operador pergunta: "Você vai continuar trabalhando (hora extra)?" — e insiste (30, 15 e 5 min antes) enquanto não houver resposta.
✅ SIM → ganha as 2 horas de hora extra permitidas. Perto do fim delas o app cobra a quantidade e fecha.
🏁 NÃO → abre na hora o popup obrigatório da quantidade: quem paletiza só confere a soma dos paletes; nas outras máquinas digita o que passou. Grava o parcial, fecha o turno e o pedido fica livre pro próximo operador continuar de onde parou.
🔌 Tablet desligou / ninguém respondeu? Continua como antes: fecha sozinho pelo horário do cronograma, sem perder o que foi apontado.
🚨 E o número passa por uma conferência: se der um ritmo impossível (foi assim que entraram 7.477 cx num trecho de 30 min no dia 12/08 — leitura do visor acumulado, que não zera na troca), o app avisa "parece a leitura acumulada do visor — coloque só o que VOCÊ passou" e pede confirmação. A mesma conferência vale no botão Finalizar turno.
🔗 A solicitação do Almoxarifado da Cartonagem agora vira ordem de compra no painel de Compras. Antes ela morria dentro do próprio app do almoxarifado — peça de manutenção virava OC, mas insumo da Cartonagem (tinta, cola, faca) não virava nada e o comprador nem ficava sabendo.
📦 A ordem chega no Compras com todos os itens, a observação e o fornecedor sugerido, marcada com o crachá "📦 Almoxarifado · nome · sol. #número" — dá pra saber de onde veio e achar a solicitação lá no almoxarifado.
👀 No almoxarifado a solicitação mostra se foi ou não. "🛒 NO COMPRAS" quando chegou lá; "⚠️ SÓ AQUI" quando não chegou — e nesse caso aparece o botão 📤 Mandar pro Compras. Se a internet cair na hora de criar, a solicitação não se perde: fica salva com o aviso pra reenviar.
🔒 Marcar "recebida" continua sendo do almoxarife. É essa marcação que repõe o saldo do estoque, e quem confere a mercadoria que chegou é quem está no almoxarifado — não o comprador de outro app. Por isso o Compras informa, mas não recebe por ele.
🔧 De quebra: o Compras chamava de "Mecânica" qualquer solicitação que não fosse da elétrica — inclusive no texto que vai pro fornecedor. Agora Almoxarifado e Compras saem com o próprio nome.
🔩 O operador agora pede PEÇA do almoxarifado — e quem libera é o ENCARREGADO. No app do operador, ao lado do Tinta/Insumos, nasceu o botão verde "🔩 Peça do almoxarifado": ele busca a peça, vê quantas tem no estoque, diz a quantidade e a urgência, e envia.
👷 O pedido NÃO vai direto pro almoxarifado — ele cai no app do encarregado (aba 📦 Requisição, seção "🙋 Pedidos dos operadores"), com aviso na hora. O encarregado ✅ Libera (aí sim vira requisição no almoxarifado, no nome do operador, com a máquina e "liberado por") ou ✖️ Recusa com o motivo.
🔔 O operador acompanha tudo no app dele: "⏳ esperando o encarregado" → "📨 liberada — com o almoxarife" → "✅ entregue — retire com o almoxarife" (ou a recusa com o motivo, ou "🛒 não tinha — foi pro Compras").
✅ Depois de liberada, é o fluxo de sempre: o almoxarifado é avisado, entrega e o saldo baixa com a trava do servidor. O almoxarife não vê nada antes do encarregado aprovar.
✅ Dá pra quitar as compras antigas de uma vez. Quando a ficha do fornecedor nasceu, toda compra já lançada apareceu em aberto — inclusive as que a fábrica pagou muito antes do sistema existir. Agora tem o botão "✅ Quitar compras antigas": na ficha (um fornecedor) ou na lista de Fornecedores (todos de uma vez).
📅 Você escolhe até quando. Ele sugere o fim do mês passado, e você muda se quiser. Tudo que foi comprado até aquela data sai de "em aberto"; o que é recente continua na conta.
👀 Ele mostra a conta antes de gravar, fornecedor por fornecedor: "FATOR CLICHERIA: 2 compras — R$ 10.000,00 · DAL COLOR: 1 compra — R$ 800,00 · TOTAL: 3 compras · R$ 10.800,00". Só grava depois que você confirma.
🟣 Isso NÃO é pagamento. Fica marcado como acerto de saldo inicial, em roxo, escrito "não é dinheiro que saiu" — e não aparece no Financeiro em "últimos pagamentos". Se entrasse como pagamento, a tela diria que saiu um dinheirão hoje que nunca saiu.
↩️ Errou a data? Cada fornecedor fica com um acerto — o ↩ desfaz tudo dele de uma vez e as compras voltam pra "em aberto".
👷 O app do encarregado ficou igual ao da manutenção nas requisições. O botão "📦 Requisitar peça do almoxarifado" ele já tinha (na tela inicial, desde a v2.33.7 — foi dele que a manutenção copiou). O que faltava era a resposta chegar sozinha: o encarregado só descobria que a peça foi entregue se abrisse a aba 📦 Requisição na mão.
🔔 Agora o app avisa: "📦 PEÇA ENTREGUE — retire com o almoxarife", "❌ cancelada" ou "🛒 não tinha no estoque, foi pro Compras" — relendo sozinho de 1 em 1 minuto, igual ao app de manutenção da v2.37.320.
🏪 O que você deve pros fornecedores agora aparece no Financeiro. Em Financeiro → Contas entrou o bloco "A pagar para fornecedores": um por fornecedor, com quantas compras estão em aberto, de quando é a mais antiga, quanto dá — e o total geral.
💵 O botão pagar de cada linha leva direto pra ficha daquele fornecedor, onde você paga a OS que quiser ou joga um valor só. Logo abaixo do bloco ficam os últimos pagamentos feitos: quando, pra quem, quanto e quantas compras aquilo abateu.
🔒 Isso não virou "conta" no Financeiro. Ele apenas lê a dívida da ficha do fornecedor. Se eu tivesse copiado, o mesmo dinheiro ficaria em dois lugares — e dois lugares com o mesmo número um dia discordam.
📊 Por isso os números lá de cima não mudaram. Dívida de fornecedor não tem data de vencimento, então ela tem o próprio total e não entra em "Vencidas" nem em "Em aberto" — quem lê aqueles quadros continua lendo o que sempre leu.
✅ Com isto a ficha do fornecedor está completa: histórico de fornecimento, gastos por dia/semana/mês, dívida, pagamento parcial e o elo com o Financeiro.
📦 Agora o pessoal da manutenção REQUISITA peça do almoxarifado pelo app — o mesmo caminho que os operadores ganharam pra tinta e cola na v2.37.318, só que pro almoxarifado de peças. No app de manutenção apareceu o botão verde "📦 Requisitar peça do almoxarifado": busca a peça, vê quantas tem no estoque, diz a quantidade e envia.
🤝 A requisição cai na aba 📋 Requisições do app do almoxarifado (que já existia) — e agora ela avisa sozinha quando chega pedido novo, sem precisar abrir a aba. Ao apertar Entregar, o saldo baixa do estoque na hora, com trava no servidor (duas pessoas não furam o saldo).
🔔 O manutentor fica sabendo da resposta no app dele: "📦 PEÇA ENTREGUE — retire com o almoxarife", ou o aviso de que não tinha no estoque e foi pro Compras. Na aba 🛒 Peças as requisições do estoque aparecem em cima, separadas das compras.
✅ O "Solicitar compra de peça" continua igual — ele é pra peça que NÃO tem no estoque (vai pro app Compras). O novo é pra peça que já está na prateleira do almoxarifado.
💰 Agora a ficha do fornecedor mostra o que você DEVE — e dá pra pagar por ali. Toda compra lançada com o nome do fornecedor entra como dívida com ele. Em cima da ficha ficam Total comprado · Já pago · Em aberto.
💵 Pagar uma OS: clique em 💵 pagar na linha e diga quanto. O clichê de R$ 1.000 da KININO com R$ 200 pagos passa a mostrar "⏳ falta R$ 800,00 · pago R$ 200,00".
🧮 Pagar o fornecedor de uma vez: o botão 💵 Pagar lá em cima aceita um valor só (ex: R$ 3.000) e abate da compra mais antiga pra mais nova. Antes de gravar ele mostra a conta item por item — "Clichê KININO — R$ 800,00 (quita) · Clichê ALPACK — R$ 2.200,00 (parcial)" — e quanto sobra em aberto.
🔒 Não deixa pagar mais do que se deve, nem na OS nem no fornecedor. E desfazer não apaga: o pagamento fica registrado como desfeito e as compras voltam pra "em aberto".
👀 Na lista de fornecedores tem agora a coluna Em aberto — dá pra ver quem você deve sem abrir um por um.
🚧 Falta a última parte: esses pagamentos ainda não aparecem no Financeiro (fluxo de pagar). Por enquanto eles vivem só na ficha do fornecedor.
🙋 O operador agora SOLICITA insumo pro almoxarifado da Cartonagem. No mesmo botão 🎨 Tinta / Insumos do app dele (que já mostra quanto tem de cada coisa no estoque), apareceu o botão "Solicitar ao almoxarifado": ele escolhe o insumo, diz a quantidade e o pedido viaja na hora — sem baixar nada do estoque ainda.
📦 No app do almoxarifado nasceu a aba 🙋 Operadores: a solicitação chega com nome do operador, máquina e o pedido que ele estava rodando, e avisa quando entra uma nova. Ao apertar Entregar, aí sim o saldo baixa do estoque — e a saída fica registrada no livro de movimentos com o pedido junto, então a ficha de tinta e o custo continuam contando certinho. Dá pra Recusar com motivo, e o operador vê a resposta no app dele ("aguardando", "entregue", "recusada").
🖥️ No sistema, o quadro "Pedidos dos operadores" (Cadastros → 🎨 Almox · Cartonagem) agora mostra essas solicitações de verdade — antes ele existia mas ficava em branco, porque nenhum app gravava naquele formato.
✅ O "Peguei — baixa na hora" continua igual: quem pega direto na prateleira registra do mesmo jeito de sempre. A novidade é só o caminho novo de pedir.
🏪 Clicar no fornecedor abre a ficha dele — o histórico de fornecimento. Em Cadastros → Fornecedores, clique no nome (ou no 📋) e você vê tudo que já foi comprado daquele fornecedor, do mais novo pro mais velho.
💰 Em cima ficam os totais: hoje, últimos 7 dias, este mês e o total comprado, mais a quebra por mês. Cada linha mostra o que foi, o nº da nota e — no caso de clichê e faca — de qual cliente é.
⚠️ Nome tem que bater. Se houver compra lançada com o nome escrito diferente do cadastro ("FATOR CLICHERIA" × "FATOR CLICHERIA LTDA"), ela não entra na conta e a ficha avisa em amarelo — em vez de somar errado ou de sumir com o valor.
🚧 Isto é a primeira parte. Por enquanto a ficha só mostra; ainda não dá pra pagar por aqui. Falta a compra virar dívida com o fornecedor e o pagamento parcial (pagar R$ 3.000 de R$ 10.000, abatendo das OS).
🔒 O orçamento não puxa mais a caixa de outro cliente. Enquanto o campo Cliente estava em branco, digitar um código que existe em outro cliente trazia a caixa dele calada — e não era só a medida: vinham também a chapa, as cores, o clichê, a faca, o R$/kg, o preço do cadastro e até o custo de tinta. Ou seja, saía preço errado na proposta.
🧪 O tamanho do estrago: sem cliente escolhido, digitar "CX 77" (que é da ALPACK) enchia o item com 900×800×700 mm, R$/kg 22,50 e preço R$ 9,99 — de um cliente que não tinha nada a ver com aquele orçamento.
✅ Agora, sem cliente o sistema não procura caixa nenhuma e a tela pede: "Escolha o cliente do orçamento primeiro". Escolheu o cliente, tudo funciona igual — inclusive no campo do Corte e Vinco, que também parou de sugerir caixa de fora.
📌 Isso valia pra cinco lugares diferentes do orçamento que procuravam por conta própria. Agora todos saem da mesma lista, e a trava mora num ponto só.
🌀 Tela nova: Confronto da Onduladeira (Análises → 🌀 Confronto da Onduladeira). Você joga a planilha do RPO e ela mostra, pedido a pedido, onde a chapa lançada no sistema não bate com o que a onduladeira fez de verdade.
📌 Por que isso importa: a chapa é a base de todo o relatório de Perda por Etapa — e muitas vezes ela é a quantidade do pedido digitada, não o que rodou. Foi isso que fez o JESSE aparecer com “4.227 caixas perdidas e R$ 15.005” quando a perda real eram 257 caixas.
🗓️ Cada rodada vai pro pedido que estava rodando naquela data — nunca somando tudo num pedido só. O mesmo número e a mesma caixa se repetem em entregas parceladas, e somar inventaria dezenas de milhares de caixas de perda.
✅ A tela separa em três: a conta fecha (com botão de gravar, um a um ou todos), as poses não batem e não dá pra gravar. Nada é gravado sozinho, e o que for gravado fica registrado na vida da caixa.
✂️ E um conserto no Perda por Etapa: ele usava o corte da onduladeira (quantas chapas saem da bobina) como se fosse quantas caixas saem de uma chapa. São coisas diferentes — quem manda é o cadastro da caixa. Um pedido da NACON aparecia com 28.600 caixas na conta sendo o pedido de 1.398.
🎨 Tinta / Insumos na tela inicial do app do operador. O botão "Peguei tinta / insumo" (que antes só aparecia dentro do pedido) agora também fica nas ⚡ Ações, do lado de Cronograma e Parada. Funciona igual: com pedido rodando, a retirada fica registrada no pedido; sem pedido, fica só no nome do operador — e tudo baixa do estoque do almoxarifado da Cartonagem, com o movimento no livro que o PCP lê.
🧑🏭 Excluir operador agora apaga DE VERDADE. O ✕ da tela de Operadores só tirava o nome da tela — no banco o operador continuava, e ele voltava a aparecer na tela de login do app do operador (foi o caso do "MTX", que ainda mostrava máquina já apagada do cadastro). Mesmo buraco que já tinha mordido nas cores e nas caixas: o salvamento é "atualiza ou cria", nunca apaga. Agora o ✕ chama a exclusão de verdade na API — e enquanto a API não for reiniciada pelo Luan, o plano B desativa o operador na hora, que já basta pra ele sumir do app e da lista.
⚖️ Quantidade pequena não trava mais o envio — agora avisa e vem pra você aprovar. O app do vendedor dizia "❌ aumente a quantidade pra enviar" e não deixava salvar: o pedido do cliente morria no celular dele e ninguém aqui ficava sabendo.
✅ Agora ele consegue mandar, mas tem que confirmar um aviso na cara: "o preço pode subir por causa da quantidade pequena — e o PCP precisa aprovar".
👀 Você vê marcado na solicitação e no pedido do vendedor: ⚖ 14,8 kg — ABAIXO do mínimo (800 kg), com o peso da rodada e o mínimo da chapa do lado. Você decide o preço sabendo disso.
🔒 Nada passa sozinho: o orçamento continua precisando da sua aprovação, e ali o sistema pergunta de novo antes de liberar o preço.
💡 Por quê: rodar menos que o mínimo da chapa não é proibido — é mais caro (setup e sobra de chapa divididos em poucas caixas). É preço, não é impedimento.
🤝 No app do vendedor, o botão "Aprovar" virou "Cliente aprovou". Lido sozinho parecia que o vendedor aprovava o orçamento — ele nunca aprovou: o que ele faz é registrar que o cliente aprovou, só depois que você libera o preço, e digitando o nome de quem aprovou. Quem gera o pedido na carteira continua sendo você.
✂️ O Corte e Vinco estava INVISÍVEL no relatório de perda. Em 12 dos 13 pedidos de agosto que rodaram na Máq. A, o degrau do corte não aparecia na escada — a coladeira aparecia direto embaixo da onduladeira.
🔍 Por que: o roteiro do pedido só sabe dizer "impressora", mas o lançamento é classificado pela máquina — quem roda na Máq. A vira "corte e vinco". Os dois nunca se encontravam.
⚠️ E não era só sumir da tela: sem o degrau do meio, a coladeira aparecia apontando mais caixa do que entrou e o pedido caía no mutirão por um desencontro que não existia.
✅ Exemplo real — KININO 23285 CX 22: antes mostrava um degrau só, "onduladeira → grampeadeira, perde 53,2%". Agora mostra a verdade:
🌀 Onduladeira 10.000 → ✂️ Corte e Vinco 8.053 (perde 1.947 · 19,5%) → 📌 Grampeadeira 4.682 (perde 3.371 · 41,9%)
🧮 O total do mês não mudou (10.645 cx, R$ 27.368) — o conserto não inventa perda nenhuma, só mostra em qual máquina ela acontece.
🧭 Junto: o pedido do KININO estava com a grampeadeira faltando no roteiro (dizia que ele parava no corte). Corrigido — só o roteiro; produção, paletes e status ficaram como estavam.
⚖️ A perda do relatório se partiu em duas, e elas não se misturam mais. Em Análises → Perda por Etapa a coluna Perda virou Lançada e Processo:
🔧 Lançada = o que o operador apontou na máquina, com motivo — a perda de ajuste de 5 caixas, a de produção de 15, a ocorrência. Esse número é dele e continua exatamente como está; nada aqui mexe nele.
⚙️ Processo = a diferença entre o que saiu da onduladeira e o que passou na máquina que sobrou sem ninguém dizer por quê.
🧮 As duas sempre somam a perda total — conferido pedido a pedido. Aparece nos quadros de cima, no "Onde a caixa some", na tabela por cliente, por dia/semana/mês/ano e no pedido a pedido.
👀 O que o número de agosto mostra: das 10.645 caixas perdidas no mês, o operador apontou 226 — as outras 10.419 (98%) são perda de processo, sem motivo nenhum. É aí que está o dinheiro.
🔔 O vendedor agora é avisado a cada passo do orçamento dele. Abriu o app, a primeira coisa que ele vê é o que andou: o nome do cliente e o que aconteceu.
✅ Orçamento pronto — "ENERBRAX · orçamento pronto · R$ 22.699,76 · nº 0021".
💬 Preço liberado (você aprovou) — o aviso já diz que dá pra aprovar junto com o cliente e leva ele direto no 🤝 Aprovar.
🤝 Aceite — dele ou do cliente pelo link, com o nome de quem aprovou. 🏭 Virou pedido na fábrica.
⛔ Reprovado — antes o "✕ Reprovar" ficava só na sua tela: o app dele continuava mostrando "orçamento pronto" num preço que a central tinha recusado. Agora chega.
👀 O aviso some quando ele toca (ou no ✓ Ok, vi), e cada aparelho conta o que já foi visto — ninguém precisa apertar nada aqui no sistema.
📨 Abrir a mesma solicitação criava outro orçamento toda vez. Entrou 3 vezes na solicitação da ENERBRAX, nasceram 3 orçamentos nº 0021 iguais, R$ 0,00 cada. Se entrasse 10 vezes, seriam 10.
🔍 Por que acontecia: o botão 💰 Fazer orçamento abria sempre como se fosse o primeiro. O número vinha da solicitação (é o mesmo negócio, o número tem que ser o mesmo) — então cada abertura fazia um documento novo com o número repetido.
✅ Agora, se a solicitação já virou orçamento, o botão ABRE aquele (✏️ Abrir orçamento nº 0021) e você edita o mesmo documento. O número permanece e não nasce mais nenhum.
✅ E a solicitação já fica ✅ Atendida ao salvar, não só quando você usa o "📨 Salvar e enviar pro vendedor" — era por isso que ela continuava aparecendo como nova, esperando um novo orçamento.
🧹 Os 3 nº 0021 que já estão lá continuam na lista — dá pra apagar os repetidos no 🗑️ do próprio cartão; abrir a solicitação agora cai no mais recente.
⚡ O Mural anunciava um ritmo que a máquina não estava fazendo. A Coladeira 01 apareceu com 14.510 cx/h numa meta de 3.500 — as 5.600 caixas eram de antes, e só o cronômetro tinha recomeçado.
🔍 Por que acontecia: o cronômetro do pedido recomeça em vários momentos (troca de turno, pedido pego de volta, lote continuado, quando o próximo operador assume), mas a contagem de caixas continua sendo a da etapa inteira. Aí o Mural dividia tudo o que já tinha sido feito pelo pouquinho de tempo do trecho novo.
✅ Agora o app marca quantas caixas já existiam quando o cronômetro liga, e o ritmo conta só o que saiu depois disso. Quem pega um pedido com 5.600 cx feitas e produz 700 aparece com o ritmo dele, não com o do turno anterior.
🤫 Enquanto não houver essa marca, o cartão não mostra ritmo nenhum — mostra a meta, que é verdade. Vale pros apontamentos que já estavam abertos hoje; some sozinho no próximo pedido que cada operador iniciar.
🔔 O sino usa exatamente a mesma conta, pra não acusar lentidão que o Mural não mostra.
⏱️ Agora dá pra corrigir o HORÁRIO de um lançamento, não só a quantidade. Faltava isso no sistema: a quantidade já dava pra arrumar, o horário não — e horário errado também estraga número (a média por hora do operador, a ficha dele, o OEE e o relatório de tempo).
🔁 Veio do caso do 23801 da TANGARA: o lançamento do Arnaldo ficou com o horário do turno do Miller ("11:51→13:05→16:11"), engolindo 1h40 que não eram dele. O app já não erra mais (v2.37.305), mas o que ficou gravado precisava de conserto.
🛡️ Só aceita hora de verdade (HH:MM) — hora torta é recusada em vez de gravar errado, e nada mais do lançamento é tocado (quantidade, paletes e o arquivamento ficam como estão).
⚠️ Precisa do Luan reiniciar o servidor pra essa parte entrar no ar.
🖨️ Operador rodando e o Mural mostrando a máquina LIVRE. Ontem à noite o Arnaldo estava produzindo na Slotter desde as 19:27 e o Mural dizia "LIVRE · ninguém apontando". Não era ele que tinha esquecido de apontar — o app tinha apontado direitinho.
🔍 O que era: ele tinha largado esse mesmo pedido às 11:31 (fim de turno). Quando pegou o pedido de volta no mesmo tablet, o app renovava a trava mas não tirava a marca de "turno encerrado" que ficou da largada. E o sistema inteiro lê essa marca como "isto não é produção viva": sumia do Mural, do sino de alertas e da conta do PCP.
⚠️ Pior que a tela: com a trava lida como morta, outro operador conseguia entrar no mesmo pedido, na mesma máquina.
✅ Agora, ao pegar o pedido de volta, o app acorda o apontamento — tira a marca, reinicia o cronômetro e recarimba os horários que vão pro registro (o mesmo cuidado da v2.37.305, pra produção não ser contada duas vezes). Reabrir um pedido que está rodando continua sem mexer em nada.
💡 Nada foi perdido: a produção do Arnaldo estava gravada, só não aparecia na tela.
🎯 No "Onde a caixa some" (Análises → Perda por Etapa) agora aparecem os dois números que fazem a conta. Antes só dizia "Onduladeira → Slotter/Impressora · 5.414 cx · 11,2%" — dava a perda, mas não dava pra ver de onde ela saiu.
✅ Agora cada linha mostra: quanto a onduladeira apontou de verdade (e quantas chapas foram, quando a chapa rende mais de uma caixa) → quanto a máquina seguinte realmente passou → o que ficou pra trás. A subtração fecha na tela: dá pra conferir sem abrir pedido por pedido.
ℹ️ Uma coisa pra não estranhar: esse bloco conta só os pedidos que perderam naquele degrau, então o número da onduladeira aqui é menor que o do quadro "Saiu da onduladeira" lá em cima — está escrito na tela também.
⚠️ E quando o operador não lança o motivo, agora o PCP lança. Apareceu um botão "⚠️ Lançar ocorrência" em dois lugares: na escada do pedido (Análises → Perda por Etapa, clicando na linha) e no modal de corrigir produção do pedido. Ele abre a ocorrência já com o pedido, a máquina e a quantidade preenchidos.
🧮 A quantidade sugerida é só o que ainda falta explicar — se o operador já apontou parte, o que sobrou é o que vem no campo, nunca a perda inteira.
✋ Nada é gravado sozinho. O número aparece pra você conferir e mudar antes de salvar, com um aviso: se a produção tiver sido lançada duas vezes numa troca de turno, essa diferença está maior que a perda de verdade. Só admin e PCP enxergam o botão.
🔁 No APP DO OPERADOR, a troca de turno parou de dobrar a produção. Aconteceu de verdade no pedido 23801 da TANGARA: o Miller lançou 2.731 no 1º turno e o Arnaldo lançou 6.904 no 2º — só que as 2.731 já estavam dentro das 6.904 (o visor da máquina não zera na virada do turno). Deu 9.635 caixas apontadas com 7.080 chapas, o que é impossível.
✅ Agora, quando o operador pega um pedido que outro largou, o app mostra quanto já foi lançado — no cartão da lista e no aviso de "continuando de onde fulano parou" (antes aparecia zero).
✅ E ao Finalizar, se o que já foi lançado mais o que ele digitou não couber no material da etapa, o app pergunta: lançar só o que ELE fez, ou o total mesmo. Ele decide — nada é corrigido escondido. Quando não tem produção de outro turno, nada muda.
⏱️ E o horário do registro virou o dele. Antes o registro do 2º turno nascia com a hora do 1º (o do Arnaldo saiu "11:51→13:05→16:11", engolindo 1h40 do Miller): a produção e o ajuste contavam duas vezes e a média por hora saía errada nos dois. Quem pega a máquina já rodando entra com ajuste zerado.
📦 A produção entrava em DOBRO quando o operador imprimia as etiquetas antes de finalizar. O botão 🖨️ Imprimir prontos e continuar já lançava as caixas daquele lote — mas não descontava de lugar nenhum. Aí, alguns minutos depois, o Finalizar (ou o fim do turno) mandava o mesmo número outra vez.
🔍 Ninguém via. Ficavam dois lançamentos com a mesma hora de início e a mesma quantidade, só com o fim 1 a 3 minutos diferente — e é justamente por esse minuto que a trava do sistema não juntava os dois. Em 6 semanas aconteceu 9 vezes em 14: KININO CX 22 marcava 9.364 caixas quando eram 4.682 (metade!), e o pedido já estava como entregue.
✅ Agora o app sabe o que já subiu. Ao imprimir o lote ele guarda o que foi lançado; no Finalizar manda só o que ainda falta. Se não falta nada, não cria lançamento nenhum — mas o pedido fecha do mesmo jeito.
🛟 Nada de produção some. Quem produzir mais depois de imprimir o lote tem essas caixas lançadas normalmente, com ou sem palete confirmado, inclusive se outro operador pegar o pedido no turno seguinte.
🧹 As 3 duplicatas que ainda estavam no ar foram arquivadas (6.006 caixas a mais): KININO CX 22, FK GRUPO 13921 e FK GRUPO 35230. Nada foi apagado. ⚠️ Passe uma vez no Estoque ▸ ♻️ Recalcular pro estoque acompanhar.
🏁 Agora o app do operador fecha o turno sozinho — sem precisar cadastrar horário de ninguém. Ele passou a usar o horário da máquina, o mesmo que você já configurou em Cronograma ▸ ⚙️ turno por máquina: a Coladeira fecha 15:48, a Grampeadeira 15:48, o Slotter vira a noite até 01:36 e o Corte e Vinco até 23:36.
⏰ Como funciona na tela do operador: aviso 20, 10 e 5 min antes, uma faixa amarela no rodapé, e no fim a pergunta "pode fechar" ou "estou de hora extra, mais 15 min". Se ninguém responder, o app fecha 5 min depois — a produção dele vira registro e o pedido fica liberado pro próximo operador continuar de onde parou. Nada se perde.
🔓 Ninguém fica trancado do lado de fora. Isso não é cadastro de horário: quem não tem horário próprio continua entrando no app a qualquer hora, inclusive de madrugada e antes de abrir o turno. A trava de entrada só existe pra quem você cadastrar em Operadores ▸ 🕐 Turno — e continua valendo como antes.
👤 Quem tem horário cadastrado continua no horário dele; o da máquina é só pra quem não tem.
🌙 Quem entrar depois do turno da máquina já ter acabado (uma hora extra que começa 16:30, por exemplo) fica sem relógio — o app não fecha ninguém por um horário que já passou.
📺 É o mesmo relógio que o Mural usa pra dizer "TURNO ENCERRADO" (v2.37.301), então os dois nunca vão discordar sobre a mesma máquina.
📄 O orçamento do App do Vendedor agora é o MESMO documento do sistema — não mais um parecido. Antes eram dois códigos diferentes desenhando a mesma nota, e as diferenças apareciam na mão do cliente.
🏷️ Saiu o "JP Micro Ondulados" escrito ao lado da logo — a logo já diz o nome, e ele só apareceu porque o nome fantasia foi preenchido no cadastro. No documento do sistema isso já tinha saído lá atrás.
✂️ O nome do vendedor não corta mais no PDF. Ele estava espremido numa coluna estreita do canto direito; agora vai no rodapé, em linha inteira, junto com a condição de pagamento — do mesmo jeito que o sistema imprime.
🧾 E o que faltava chegar no app chegou: quando o cliente tem carta de isenção, o IPI sai como "ISENTO — mediante carta de isenção"; a observação ganha o destaque azul; o CNPJ aparece embaixo do nome do cliente.
🔒 O documento do PCP não mudou nada — conferido letra por letra contra o de antes. O que mudou foi o do vendedor, que passou a ser esse mesmo.
📺 No Mural da Fábrica, operador que já foi embora aparecia RODANDO a noite inteira. A Coladeira 01 mostrava "RODANDO · Mirailton · há 7h44 · 0 de 5.000 cx" às 20h45, com a fábrica vazia — ele saiu sem apertar Finalizar turno e o apontamento ficou aberto pra sempre.
✅ Agora o mural olha o relógio da máquina. Passou do fim do turno daquela máquina (a Coladeira fecha 15:48, o Slotter vira a noite até 01:36) e ninguém mais apontou, o cartão fica cinza e escreve TURNO ENCERRADO · turno acabou 15:48 · sem apontar desde 13:04. Para de contar como "rodando" lá em cima.
⏱️ Quem está de hora extra continua verde: tem 2 horas de folga depois do fim do turno, e a folga também conta a partir da última vez que o operador mexeu no app. Só apaga quando as duas coisas passaram.
🔓 E dá pra soltar o pedido no mesmo dia. Esse apontamento entra no 🔓 Destravar, no alto do mural — antes só entrava depois de 3 dias largado, e o pedido ficava preso pro próximo operador. Nada é apagado: o que foi produzido continua guardado.
💡 Quem quiser que o próprio app feche o turno sozinho, é só preencher o horário em Operadores ▸ 🕐 Turno — hoje quase ninguém tem, e por isso o app nunca fecha nada sozinho.
🖨️ O orçamento impresso pelo App do Vendedor saía com o fundo PRETO — e pior que feio: metade sumia. No PDF do KININO nº 0019 o nome do cliente, a quantidade e o preço unitário ficaram pretos no fundo preto, ilegíveis. Ele imprimia a própria tela do app, e o fundo escuro ia junto pro papel.
✅ Agora sai branco e limpo, igual o do sistema — o app monta uma folha própria pra impressão, sem nada do visual escuro. Vale pro "Imprimir / PDF" no celular e no computador.
📤 E o botão 📱 WhatsApp agora manda o PDF, não um textão. No celular abre o "compartilhar" do aparelho já com o arquivo CLIENTE - Orç NNNN - dd-mm-aa.pdf anexado — é só escolher o contato. No computador, baixa o PDF e abre o WhatsApp com o texto pra você anexar.
🔒 Sem internet o botão ainda manda o texto, como antes — nunca fica sem mandar nada.
✂️ No orçamento, o campo "ou puxar de uma caixa já cadastrada" do Corte e Vinco também virou campo de digitar. Era o último que ainda era lista pra rolar. Agora você escreve o começo do código e ele vai aparecendo.
📐 Cada sugestão mostra o que é a caixa: apelido, o molde por caixa, as poses e o valor da faca — "CV 100 · Bandeja Pizza · 950×750 mm/cx · 4 poses · faca R$ 850,00". Dá pra escolher sem abrir o cadastro.
✏️ Escreveu algo que não é caixa Corte e Vinco daquele cliente? Ele avisa e manda usar o 🎨 Projetar Corte e Vinco — em vez de escolher uma parecida por conta própria.
🔒 Continua mostrando só as caixas do cliente do orçamento, e a pergunta de como cobrar a faca só aparece quando você escolhe a caixa de verdade — não enquanto digita.
🏷️ A etiqueta da amostra imprimia "Gramatura / Coluna" vazia. Saía "— / —" mesmo com a chapa cadastrada com os dois números. O sistema procurava esses campos no cadastro da chapa com um nome que não existe lá — então nunca achava nada, e nem tinha como dar erro.
✅ Agora sai o que está na chapa. A caixa da chapa "ONDA B 357" imprime 357 g/m² / 4 kgf. Vale pra etiqueta nova e pra reimpressão, tanto no sistema quanto no app de Desenvolvimento.
🌐 O portal do cliente também. Naquela página que o cliente abre pelo link, as fichas "Gramatura" e "Coluna" estavam vazias pelo mesmo motivo — agora os dois lugares leem do mesmo lugar e não têm como discordar.
🔒 Chapa que ainda não teve a coluna medida continua imprimindo —, nunca "0 kgf" — número zero na etiqueta parece medida de verdade.
💸 O orçamento estava cobrando barato demais nas caixas de ABA TRANSPASSADA — de 11% a 15% a menos de papelão. Agora não mais.
🔍 Por quê: a aba transpassada existe no cadastro da caixa desde sempre — é a caixa em que a aba de baixo vai INTEIRA (a largura toda), e não a metade, pra as duas se sobreporem e reforçarem o fundo. Só que o orçamento não conhecia esse modelo: ele calculava toda maleta com as duas abas pela metade. A conta saía com uma meia aba a menos de papelão do que a caixa gasta de verdade — e ninguém via, porque o número parecia normal.
📦 O que muda: o "Estilo da caixa" ganhou Maleta Aba Transpassada (B), (C), (BB) e (BC). Escolhendo ela — ou puxando uma caixa que já está cadastrada assim — a chapa sai com a largura certa, e o peso e o preço vêm junto. O desenho ao lado também mostra a aba de baixo maior que a de cima, como ela é.
🎯 Nas 6 caixas transpassadas do cadastro (todas do FK GRUPO: 31459, 31644, 35597, 35600, 44958 e 44959), a diferença era de R$ 1,58 a R$ 3,09 por caixa. Num pedido de 5.000 caixas isso é de R$ 7.875 a R$ 15.458 que não estavam sendo cobrados.
✏️ Aba medida na mão continua valendo: a 44958 usa 300 mm em vez da largura cheia, e o orçamento respeita o que está no cadastro dela.
🔒 Maleta normal, meia maleta e corte e vinco: nada mudou — conferido nas 142 maletas do cadastro.
⚡ Um item só volta a ser um clique. Na versão anterior tudo passava pela lista, e pra lançar uma coisa avulsa dava dois cliques. Agora são dois botões: ➕ Lançar grava na hora o que está no formulário, e 📝 Pôr na lista é pra quando você vai juntar vários itens da mesma compra.
🤝 E os dois se entendem: se você já tem itens na lista e digita mais um no formulário, o ➕ Lançar manda tudo junto — o que você acabou de digitar não fica pra trás. O botão da lista já mostra a conta certa e avisa: "↑ inclui o item de R$ 554,40 que está no formulário acima".
🔒 O resto continua igual: a conferência com a nota, o pedido que reabre pra dar entrada no que chegou, e o estoque do almoxarifado sendo mexido só na hora de lançar.
🛒 Agora você vai adicionando os itens numa lista e lança tudo de uma vez só. O botão virou ➕ Adicionar item: cada item entra numa lista logo abaixo, e quando estiver tudo lá você clica em ✅ Lançar os N itens.
👀 O melhor disso: dá pra conferir ANTES de gravar. Enquanto monta a lista, o aviso da nota já soma o que está nela ("2 itens (0 lançados + 2 na lista) — faltam R$ 554,40"). Errou um item? Clica no 🗑️ e ele sai da lista — sem virar lançamento pra depois ter que apagar (e sem mexer no estoque à toa).
📦 Pedido de compra que chega em partes: abre o pedido, dá entrada no que chegou, e depois volta nele. O campo do nº agora sugere os pedidos que já estão abertos — mostra de quem é e quanto falta pra fechar ("10 JP · SILRESIN · 2 itens · faltam R$ 554,40") — e ao escolher já traz o fornecedor e o total sozinho.
✏️ Compra avulsa, sem nº de pedido, continua funcionando igual: adiciona e lança.
🔒 O estoque do almoxarifado só é mexido na hora do Lançar — nunca enquanto você está montando a lista.
🧾 Agora dá pra lançar a NOTA INTEIRA de uma vez, no Lançamento de Insumos. Uma compra de tinta vem com 5 itens na mesma nota — antes cada um virava um lançamento solto e no fim do mês não tinha como conferir com o papel do fornecedor.
✍️ Como fica: digite o nº da nota, o fornecedor e o total da nota uma vez só. Aí vai lançando item por item — o cabeçalho não se apaga entre um e outro. Quando acabar aquela compra, clique em 🆕 Começar outra nota.
✅ E ele confere sozinho: enquanto você lança, aparece "3 itens · somam R$ 2.041,60 — bate com o total da nota", ou "faltam R$ 554,40" se ainda tem item pra entrar, ou "passou R$ 241,60" se algum preço saiu errado. Pega item esquecido antes de fechar o mês.
📋 Na lista do mês os itens da mesma nota saem juntos, embaixo de um cabeçalho com o total da compra. Lançamento sem nº de nota continua uma linha solta, do jeito que sempre foi.
⚠️ Duas notas com o mesmo número de fornecedores diferentes (a NF 1234 da DAL COLOR e a NF 1234 da SILRESIN) continuam separadas — o número da nota é do fornecedor, não é único.
📦 No orçamento, o campo da caixa também passou a falar. A sugestão mostra o apelido, as medidas e a onda de cada caixa ("CX 09 · Caixa Salgadinho · 400×300×200 mm · onda BB"), e quando o que você escreveu não é caixa cadastrada ele avisa, em vez de ficar mudo como antes.
🔒 E se o cliente ainda não foi escolhido, ele avisa em amarelo: sem cliente o sistema procura em TODAS as caixas e pode trazer a de outro cliente.
📦 MEIA MALETA: a caixa que fecha só o fundo. É a maleta de sempre sem as abas de cima. Agora dá pra orçar e cadastrar ela do jeito certo — antes só existia a maleta inteira, e quem vendia meia maleta pagava (e cobrava) por uma aba de papelão que não vai na chapa.
💰 No Orçamento, o "Estilo da caixa" ganhou Meia Maleta (B), (C), (BB) e (BC), do lado das Maletas Normais. A conta muda só na largura da chapa: entra uma aba, não duas. Uma caixa 203×203×206 de onda B sai 874 × 315 mm em vez de 874 × 418 — 24,6% menos papelão, e o peso e o preço caem junto sozinhos. O comprimento (o vulto, que é o que a impressora mede) não muda.
✏️ O desenho ao lado desenha ela de verdade: os 4 painéis C·L·C·L, a aba de cola, só o vinco de baixo e as abas do fundo — sem a faixa de cima, com as cotas certas.
📋 No cadastro da caixa, o campo Modelo ganhou "📦 Meia maleta (só a aba do fundo)". Escolhendo ela, o riscador passa a ter duas faixas — corpo + aba do fundo — e a chapa, o peso e o valor se acertam na hora. A medida da impressora continua a mesma.
🏭 A fábrica enxerga igual: a ficha do operador e o card da onduladeira mostram as duas faixas com o nome certo ("corpo" e "aba fundo"), no lugar do "aba · corpo · aba" fixo de antes. Cadastro, orçamento e máquina chegam no mesmo número (315 mm no exemplo acima).
🤝 Vendedor e cliente leem "Meia Maleta (BB)" na proposta, não um código.
🔒 Maleta normal, aba transpassada, bandeja, auto-piso e corte e vinco: nada mudou — conferido caixa por caixa.
👤 O campo Cliente do orçamento agora diz o que está acontecendo. Ele já deixava digitar, mas as sugestões eram só o nome pelado e, se o nome digitado não fosse de ninguém cadastrado, o orçamento saía assim mesmo — calado, sem vendedor e sem a condição de pagamento. Agora tem uma linha embaixo do campo que avisa na hora.
📍 Cada sugestão mostra a cidade/UF do cliente, pra você não confundir dois de nome parecido. Quem está inativo aparece marcado com 🔴 e vai pro fim da lista.
⚠️ Nome repetido no cadastro é o caso mais perigoso — o sistema se recusa a adivinhar qual dos dois é (e faz certo), só que antes ninguém via isso. Agora ele fala: "tem 2 clientes com esse mesmo nome (Marília/SP, Garça/SP) — o orçamento vai sair sem vendedor e sem a condição de pagamento".
✏️ Cliente que não está no cadastro continua podendo ser orçado — só que agora com o aviso na tela, em vez de descobrir depois.
🔎 No Lançamento de Insumos, o campo "Qual produto (do estoque)" virou campo de digitar. Antes era uma lista comprida que só dava pra abrir e rolar até achar. Agora você escreve o começo do nome e os produtos vão aparecendo — igual aos campos de Fornecedor e de Cliente que já ficam ali do lado.
💰 Cada sugestão já mostra o preço e o saldo do almoxarifado ("R$ 15,00/kg · saldo 12 kg"), então dá pra escolher sem abrir outra tela. Ao clicar, continua puxando tudo como antes: preço, unidade, balde, fornecedor e a conta do valor total.
✍️ Comprou algo que não está no almoxarifado? É só escrever o nome e digitar o valor na mão — o sistema avisa embaixo que aquele produto não está no estoque, em vez de escolher um parecido por conta própria.
⚠️ Se dois produtos tiverem o mesmo nome, a lista mostra o fornecedor de cada um pra você saber qual é qual.
↩️ Corte produziu depois do fechamento: agora dá pra reabrir. Caso real do REVAL FUNDO M: 14 paletes prontos de ontem e 500 cx cortadas hoje — que não tinham como ser coladas nem etiquetadas. O pedido não aparecia em máquina nenhuma e não havia botão na tela que resolvesse: só o Reiniciar, que anula a produção.
🔍 Por quê: o botão "↩️ Reabrir a Coladeira" calculava o que falta por diferença de totais (o que o corte entregou menos o que o fechamento fez). No Corte e Vinco isso vira negativo por natureza — o corte lança chapa e a coladeira lança caixa, e 1 chapa vira várias caixas. Aqui: 7.658 entregues contra 11.073 fechadas = −3.415, e o botão sumia.
✅ Agora a pergunta é outra: saiu produção do corte depois que a etapa de fechamento foi concluída? Se saiu, é trabalho novo — o botão aparece com o número certo ("terminar 500") e o pedido volta pro operador. As 500 saem num lote novo de etiquetas, e o que já foi lançado e etiquetado continua contando, sem mexer.
🔒 Pedido com saldo normal continua exatamente como era.
🏷️ A pergunta do lote não aparecia pra Mayara — agora aparece. O caso real do FK 35600: ela finalizou o pedido com 1 palete (130 cx), a etiqueta não saiu, o pedido saiu dos concluídos dela e as 130 cx foram pro estoque. Agora tem chapa e falta o resto — mas ao pegar o pedido de novo o app ficava calado.
🔍 Por quê: quando o operador finaliza, o app apaga o progresso daquele pedido. Eu procurava o lote anterior só dentro do progresso — que sobrevive no fim de turno, mas não sobrevive ao finalizar. Pegando o pedido de novo, nascia um progresso vazio: sem palete carimbado, sem lote pra oferecer.
✅ Agora o lote é procurado onde ele dura: no concluído do dia, nos registros do pedido e, se preciso, direto no banco. A pergunta aparece, e continuando no mesmo lote a etiqueta sai com o palete de ontem junto, numerado na sequência.
🔒 De quebra, um risco que já existia: pedido finalizado e pego de novo abria "lote 1" outra vez — dois paletes diferentes com o MESMO QR, que a Expedição recusaria como "já bipado". Agora o número do lote continua de onde parou, mesmo quem responder "começar o próximo lote".
🎨 A logo da empresa agora aparece em TUDO — e o nome virou "JP EMBALAGEM".
🏷️ A logo entrou em todos os 19 apps. Antes só 3 tinham (Central, Operador e Expedição); os outros 16 não tinham logo nenhuma. Agora todos abrem com ela no cabeçalho, e as telas de entrar ("Quem é você?") mostram a logo grande.
📄 E em todo documento que sai impresso: Relatório de Entregas, Curva ABC, Eficiência, Cronograma do dia e da semana, Romaneio, Plano de Carga, Ficha do Operador, Laudo Técnico, Solicitação de Paletes, Conversão de Orçamentos, Ordem de Compra, Solicitação de Compra de Peças e do Almoxarifado.
🤝 No que o cliente vê: o orçamento sai com a logo nos 4 lugares onde ele é montado — no sistema, no app do Vendedor, na página de aprovação e no portal. Antes cada um tinha a sua cópia da logo e podiam ficar diferentes; agora todos leem do mesmo lugar.
⚙️ Onde se troca a logo: continua em Cadastros → Dados da Empresa. Trocou ali, troca em todo canto de uma vez — não precisa mexer em mais nada.
✏️ "JP EMBALAGENS" virou "JP EMBALAGEM" em 129 lugares: título das abas, cabeçalhos, rodapé dos relatórios, laudo, mensagens de WhatsApp, assunto e remetente dos e-mails, etiquetas de amostra e clichê, nome dos apps no celular.
🚫 Duas coisas ficaram como estavam, de propósito: a etiqueta térmica de clichê/faca (você mandou tirar o nome dela na v2.34.52, pedido do chão, pra sobrar espaço pro número) e as entradas antigas deste changelog, que são o histórico.
🗑️ Excluir cliente agora funciona de verdade — antes o botão mentia. Você clicava em Excluir, o cliente sumia da tela e parecia resolvido; no próximo carregamento ele voltava. Motivo: faltava a peça no servidor que apaga, e a tela usava a gravação normal, que só cria e atualiza — nunca apaga. É a mesma coisa que já tinha acontecido com o cadastro de cores e com o de caixas.
✅ O que muda: o botão agora manda apagar no servidor primeiro. Só quando o servidor confirma é que o cliente sai da tela. Se der qualquer problema — internet caída, servidor fora do ar — ele continua na lista e você recebe o aviso do que aconteceu, em vez de achar que apagou.
🔒 Trava dupla contra apagar cliente com histórico. A tela já avisava quando o cliente tinha pedido ou caixa vinculados; agora o servidor confere de novo antes de apagar, e recusa dizendo quantos são. Isso importa porque apagar não some com o pedido — ele fica órfão, sem cadastro, e o vendedor perde a comissão dele sem ninguém perceber. Foi exatamente o risco do "GRS Toys", que tinha 3 pedidos entregues de R$ 34.400 pendurados.
📌 Pra apagar um cliente que tem histórico: primeiro passe os pedidos dele pro cadastro certo (foi o que fizemos com o GRS), ou deixe o cliente como Inativo.
🏷️ "Continuar no mesmo lote": vale na Coladeira E na Grampeadeira. Emenda da v2.37.282 — a pergunta já aparecia nas duas máquinas (o Mirailton na Coladeira e a Mayara na Grampeadeira são justamente quem mais paletiza: 24 e 8 lotes nos registros), mas faltava uma trava.
🔒 O que estava aberto: a pergunta não olhava em qual máquina o operador estava. Um pedido que passa pela Slotter e pela Grampeadeira (é o caso do FK 35600) podia mostrar a pergunta lá na Slotter — onde não existe palete nem etiqueta pra imprimir. Agora ela só aparece na máquina de fechamento (Coladeira, Grampeadeira, ou qualquer outra cadastrada como etapa final) e quando o progresso é da etapa daquela máquina.
✅ Nada muda pra quem já usa: na Coladeira e na Grampeadeira a pergunta continua igual.
🔍 Investigação da Fernanda — e dois consertos que saíram dela.
✅ Primeiro, a boa notícia: a Fernanda Zanela está cadastrada e certa (login fernanda, WhatsApp preenchido, 4 clientes no nome dela: Deusa Alimentos, Enerbrax, GRS Toys e Three Life Lab). O cadastro tem 6 vendedores, todos com WhatsApp. O que estava errado era o aviso da versão anterior, que dizia que faltava cadastro — o texto já foi corrigido no histórico.
🐛 Conserto 1 — o app de Desenvolvimento só enxergava 2 vendedores dos 6. Na hora de registrar uma amostra, o campo "quem trouxe este cliente" só oferecia o Armando e o Maycon: sumiam Fernanda, André, Tatiane e JP Embalagem. Ele estava lendo uma lista velha e abandonada, congelada em 07/08, em vez do cadastro de verdade. Quem registrasse uma amostra de cliente da Fernanda não tinha como escolher ela — e a amostra nascia sem vendedor. Agora lê o cadastro certo.
📱 Conserto 2 — o botão de avisar no WhatsApp agora acha o vendedor pelo CLIENTE também. O orçamento pega o vendedor do cliente na hora em que é criado; se o cliente ganha vendedor depois, o orçamento fica órfão pra sempre. Foi o caso do KININO: virou cliente da Tatiane 2h30 depois do orçamento nascer, e por isso aparecia como "sem vendedor". Agora, quando o orçamento não tem vendedor, o sistema olha quem atende aquele cliente no cadastro e mostra 📱 Avisar Tatiane (do cliente). É só pra saber a quem avisar — não muda nada no orçamento.
📋 O que continua sem dono: Mitto, Jesse e Grupo Polar não têm vendedor nem no orçamento nem no cadastro do cliente — a linha agora diz isso com todas as letras ("sem vendedor — e o cliente também não tem"). São 20 dos 35 clientes sem vendedor no cadastro; preenchendo lá, o aviso passa a funcionar sozinho.
⏳ O prazo de entrega agora manda na data do pedido do vendedor. Em Orçamento → ⚙️ Configurações → Comercial apareceu o ajuste “Prazo de entrega padrão” (nasce com 20 dias, que é o que a casa já usava por baixo). Ele é o piso da data: no app, quando o vendedor lança um pedido, a entrega já vem com o prazo cheio e não dá pra puxar pra antes — o calendário nem deixa escolher, e se insistir a tela avisa: “a entrega mais cedo é 31/08 (prazo de 20 dias). Pra antecipar, escreva na observação — quem decide é o PCP.”
Jogar pra frente pode à vontade. E o prazo do CLIENTE (Cadastros → Clientes → “Prazo padrão”) continua mandando mais que o da casa: cliente com 7 dias cadastrados abre o pedido já com 7 dias. Trocou de cliente no meio do pedido, a data volta pro prazo daquele cliente.
A conversão de orçamento em pedido também passou a usar esse ajuste: antes, cliente sem prazo cadastrado caía num 20 fixo escondido no código — agora é o número que você configurou.
⚠️ Não confunda com a “Validade padrão”, logo acima dele: aquela é quanto tempo o preço vale; esta é quanto tempo a fábrica precisa pra entregar.
🏷️ Etiqueta que não saiu: dá pra continuar no MESMO lote. O caso que estava acontecendo direto: o operador larga o pedido no fim do turno, o sistema fecha o lote sozinho e ninguém imprime a etiqueta. No dia seguinte a produção continuava no lote 2 — e o lote 1 ficava pra sempre no aviso "produto pronto, falta imprimir etiqueta", às vezes com 1 palete só.
👉 Agora, ao pegar o pedido, se a etiqueta do lote anterior não saiu, o app pergunta: "Continuar no lote 1?" — dizendo quantos paletes e quantas caixas estão parados lá.
• Continuar no lote 1 → tudo que for produzido dali pra frente entra nele, e a etiqueta sai de uma vez só, com os paletes numerados na sequência (1, 2, 3…). O palete de ontem, que estava sem etiqueta, sai junto.
• Começar o lote 2 → é o jeito de sempre, e o lote 1 continua esperando a etiqueta dele.
✅ Se a etiqueta JÁ tinha sido impressa, não pergunta nada — a produção nova abre o lote 2, como sempre foi. E se o PCP imprimir o lote no meio do caminho, o app percebe e abre o lote novo sozinho: palete nenhum entra em lote já impresso (sairia sem etiqueta e ninguém saberia).
🖨️ No painel central, o aviso de etiqueta agora mostra uma linha por lote, com o total certo. Antes, um lote com dois turnos apareceria duas vezes — e imprimir uma delas apagava o aviso das duas, deixando metade dos paletes sem etiqueta.
🔒 Por dentro: cada palete passou a guardar a posição dele no lote. Sem isso, o primeiro palete do turno novo nasceria com o mesmo QR do primeiro palete de ontem, e a Expedição recusaria a bipagem como "já bipado". Etiqueta antiga continua valendo igual — nada do que já foi impresso muda.
📱 Botão pra avisar o vendedor no WhatsApp. No relatório 📊 Conversão, na lista "o que dá pra fazer agora", cada orçamento vencendo ganhou o botão verde 📱 Avisar [nome]. Ele abre o WhatsApp com o recado já escrito:
Oi, Maycon! Lembrete do orçamento Nº 0016 — TESSE, R$ 12.000,00.
Ele vence em 2 dias (validade até 12/08/2026).
Vale um toque no cliente pra fechar antes de vencer.
Se o orçamento já venceu, o texto muda sozinho: "Dá pra revalidar o preço se o cliente ainda tiver interesse".
✋ A mensagem NÃO sai sozinha. O botão abre o WhatsApp com o texto pronto — você lê, muda o que quiser e aperta enviar. É o mesmo jeito do romaneio, da ordem de compra e da escala. Mensagem automática indo pro celular de uma pessoa é coisa que a gente evita de propósito.
✅ Funciona hoje, sem precisar cadastrar nada: o botão aparece nos orçamentos do Armando (ECOLUBRI e KIMETAIS) e da Fernanda (ENERBRAX) — os três estão com WhatsApp no cadastro.
Quando não dá pra avisar, a linha diz o motivo em vez de esconder o botão: "sem vendedor no orçamento" (4 orçamentos foram criados aqui no PCP sem escolher vendedor), "vendedor sem WhatsApp no cadastro" ou "vendedor não está no cadastro".
📌 Correção do texto original desta versão: aqui estava escrito que nenhum vendedor tinha WhatsApp e que a Fernanda não estava cadastrada. Estava errado — eu tinha lido uma lista velha e abandonada de vendedores, em vez do cadastro de verdade. O cadastro tem 6 vendedores (André, Armando, Fernanda, JP Embalagem, Tatiane e Maycon) e quase todos com WhatsApp. Nada precisa ser cadastrado.
🧪 O que o cliente aprova no Desenvolvimento agora aparece como aceite no orçamento. Quando o cliente aprova o orçamento no portal (aquele ✅ “Aprovado por Fulano”), o sistema entende sozinho: o orçamento vira 🤝 Aceito por [quem assinou] (aprovou o orçamento no Desenvolvimento) e o 📋 Gerar caixas + pedidos aparece — sem você registrar aceite de novo na mão.
Vale mesmo com o orçamento ainda pendente: o cliente aprovou o preço que já recebeu, não faz sentido o aceite dele ficar invisível esperando alguém clicar em “Aprovar preço”.
Se a caixa ainda estiver no meio do Desenvolvimento, o card avisa: “o cliente aceitou o preço, mas o Desenvolvimento ainda não liberou — falta amostra/arte”. Aí você decide se gera o pedido ou espera.
📱 E o app do vendedor ficou limpo, do jeito que ele pediu:
• A aba 📦 Pedidos mostra só o que ele lançou. A lista “🏭 Na fábrica” saiu — aquilo já está na aba Clientes, organizado por cliente, e enchia a tela com mais de cem cartões.
• Os pedidos lançados saíram da aba de Orçamentos: cada coisa na sua aba.
• O orçamento virou drop down: fechado mostra só cliente, número, situação e total; toca e abre as caixas, os preços e os botões. O aviso de prazo continua aparecendo com o cartão fechado — é recado pra ele agir.
🧑💼 Agora o VENDEDOR também é avisado quando o orçamento dele está perto de vencer. Na v2.37.276 o aviso ficou só pra você, aqui no sistema. Agora ele vê no celular dele, sem precisar perguntar nada:
• Uma faixa no topo da aba Orçam. assim que abre: "3 vencendo em até 5 dias — R$ 63.624,74 · 1 já venceu — R$ 10.191,36";
• Um aviso no cartão de cada orçamento — ⏳ vence hoje / vence amanhã / vence em 4 dias / 💤 venceu há 2 dias — com o recado do que fazer ("bom momento pra dar um toque no cliente");
• E cada cartão passou a mostrar a data em que vence ("validade 20 dias · até 14/08/2026"), em vez de só os dias — antes ele tinha que fazer a conta de cabeça.
🤝 Orçamento já aceito não aparece no aviso, mesmo fora da validade: aceite não vence. Reprovado e o que virou pedido também ficam de fora.
🐛 E o conserto que estava por trás disso — a data de validade do app do vendedor estava ERRADA. O app contava a validade a partir do dia em que o orçamento foi mandado pra ele, enquanto o sistema e o link do cliente contam do dia em que o orçamento foi criado. Eram duas datas de "válido até" no mesmo orçamento — e a que ia pro cliente por WhatsApp e no PDF era a do app. Pior: reeditar o orçamento esticava a validade só no app dele, sem ninguém perceber.
✅ Agora é uma data só nos três lugares (sistema, app do vendedor e link do cliente). Orçamento antigo, que foi enviado antes desta versão, continua abrindo com a data que sempre teve — nada muda pra trás.
📄 Copiar caixa: a mesma caixa com outro rótulo, sem redigitar tudo de novo. Abrindo uma caixa em Cadastros → Caixas, apareceu o botão 📄 Copiar caixa ao lado do Salvar. Você escreve só a referência nova e a caixa nasce igualzinha: medidas, chapa, composição, poses, roteiro e máquina, paletização, peso e preço.
🔧 O que NÃO vem junto — de propósito: clichê, faca e arte (imagem, PDF e a ficha de tinta que sai dela). Essas três são da caixa NOVA: o número do clichê e da faca vêm do contador único da fábrica (duas caixas com o mesmo número quebrariam a rastreabilidade da ferramenta), e a arte é outro rótulo — copiada, iria pra impressão errada. Por isso a cópia abre na hora com o cursor no Nº do Clichê, esperando você preencher.
A caixa nova também não herda o histórico nem a última entrega da antiga — ela nasce hoje. No histórico dela fica registrado “Cópia de [referência]”, pra você sempre saber de onde veio. E se o cliente já tiver uma caixa com aquela referência, o sistema avisa e não deixa duplicar.
⏳ O sistema agora avisa quando o orçamento está perto de vencer. Antes o prazo de validade só existia no papel: passava a data e ninguém era avisado — o cliente sumia e a gente descobria depois.
🔔 No sino de alertas (o mesmo do topo, junto com máquina parada) entraram duas linhas novas:
• "3 orçamento(s) vencendo — R$ 63.624,74" — os que ainda estão no prazo, com cliente, número, valor e quando vence cada um;
• "1 orçamento venceu sem resposta" — a validade acabou e o cliente não falou nada.
🏷️ E na lista de Orçamentos, cada cartão ganhou o selo do prazo do lado do status: ⏳ vence hoje, ⏳ vence amanhã, ⏳ vence em 4 dias, 💤 venceu ontem. Não precisa abrir nada pra ver qual está apertando.
⚙️ Você escolhe a antecedência no botão de engrenagem do sino: o padrão avisa com 5 dias, e o vencido fica 3 dias no sino antes de sair (senão orçamento vencido em março moraria lá pra sempre). Depois disso ele continua no relatório 📊 Conversão.
🔒 Quem não vê orçamento, não recebe o aviso. O alerta mostra cliente e valor, então só aparece pra quem já tem a aba 💰 Orçamentos liberada — encarregado e operador não veem. E esse aviso não vai pro chat da fábrica: é assunto do comercial, fica na tela.
📅 Conserto junto: a conta do prazo passou a ser por dia de calendário. Contando por hora, um orçamento que vencia hoje às 14h aparecia como "vence amanhã" de manhã e "vencido" às 15h — dois textos errados no mesmo dia. Agora o orçamento vale o dia inteiro do vencimento, que é o que o cliente entende por validade. Quem já foi aceito pelo cliente nunca entra nessa conta — aceite não vence.
🔗 Agora o CLIENTE aprova o orçamento pelo link — e o pedido do vendedor virou um pedido de verdade, com várias caixas.
1) Link pro cliente aprovar. No orçamento aprovado apareceu o botão 🔗 Link pro cliente: clicou, o link já vai copiado pro WhatsApp. O cliente abre uma página limpa com as caixas, medidas, preço por caixa (3 casas), IPI, ferramenta, peso e o total — e o botão ✅ Aprovar este orçamento. Ele escreve o nome (e o cargo) e pronto: no seu sistema o orçamento vira 🤝 Aceito por [nome] (pelo link do cliente) e libera o 📋 Gerar caixas + pedidos. Ficam guardados a data, a hora e o IP de quem aprovou.
⚠️ Esta parte precisa do Luan reiniciar a API (não mexe no banco). Até lá, o aceite pelo app do vendedor e o 🤝 Registrar aceite continuam funcionando normal.
2) Lançar pedido com VÁRIAS caixas. O 📦 Lançar pedido do app nasceu com uma caixa só — agora tem o ➕ Adicionar caixa, cada uma com quantidade e preço próprios, e o total do pedido somado embaixo. Quando você aprova, cada caixa vira um pedido na carteira.
3) Peso e peso mínimo, igual no orçamento. Cada caixa do pedido mostra o peso (kg/cx e total, pela gramatura da chapa do cadastro) e barra o envio quando fica abaixo do mínimo de produção — o vendedor descobre na hora, não depois de você recusar.
4) Editar e acompanhar. Enquanto você não aprova, o vendedor pode ✏️ Editar (mudar quantidade, preço, caixa) ou 🗑️ Excluir o pedido que lançou — e o cartão aqui avisa “o vendedor editou este pedido”. Depois de aprovado, os botões somem: já é produção.
5) Aba 📦 Pedidos no app. Nova aba com duas listas: 📤 Lançados por você (esperando o PCP) e 🏭 Na fábrica — os pedidos de verdade dos clientes dele, com a fase de cada um. É aí que o orçamento que virou pedido aparece, marcado com o número do orçamento que deu origem.
🤝 O vendedor agora lança o preço, o PCP aprova, e o pedido só nasce depois do aceite. E ele pode lançar pedido de recompra direto pelo app.
1) Preço no app. Cada caixa do orçamento ganhou o campo 💰 Preço por caixa. Se a caixa já tem preço no cadastro, ele aparece na hora (“📋 Cadastro: R$ 0,712/cx”). Acima do cadastro pode; se ele colocar abaixo, fica vermelho avisando que a diferença pode ser descontada da comissão dele — e ele tem que confirmar pra enviar. Ninguém dá desconto sem saber.
2) O PCP vê os dois números. Na fila de 📨 Solicitações, cada caixa mostra o preço pedido comparado com o do cadastro: ↑ acima, = igual ou ⚠ ABAIXO (dizendo que o vendedor foi avisado da comissão), mais o total que ele pediu. Seu cálculo continua mandando — isso é informação pra decidir.
3) A corrente de aprovação. O vendedor lança → você clica em ✓ Aprovar preço → o orçamento fica ⏳ Aguardando aceite → o vendedor confirma pelo app (botão 🤝 Cliente aprovou, com o nome de quem aprovou) ou você registra pelo 🤝 Registrar aceite → só então aparece o 📋 Gerar caixas + pedidos. O aceite não cria pedido sozinho: quem põe pedido na carteira continua sendo o PCP. O card mostra quem aceitou e quando, dos dois lados.
4) 📦 Lançar pedido (recompra). Cliente ligou pedindo mais 5.000 da caixa que já faz? Não precisa de orçamento novo: na tela de Clientes do app tem o botão 📦 Lançar pedido — ele escolhe a caixa do cadastro daquele cliente, a quantidade, a data e o preço (que já vem preenchido com o do cadastro, com a mesma regra do desconto).
5) E você aprova. Isso cai numa fila nova em 📨 Solicitações → 📦 Pedidos lançados pelo vendedor. O cartão mostra quantidade, data, preço × cadastro e, quando vier ABAIXO, um aviso vermelho com quantos reais a menos o pedido tem. Aprovou: o pedido nasce na carteira em “Esperando programação”, já com a máquina que a caixa define no cadastro. Recusou: você escreve o motivo e ele lê no app.
Na tela de Clientes do app ficaram as 3 ações na mão: ➕ Orçamento, 📦 Lançar pedido e 🤝 Aprovar (com o número do que está esperando ele). E ele acompanha os pedidos que lançou: aguardando o PCP, aprovado ou recusado.
🔧 De quebra: a tela de Solicitações podia abrir quebrada num PC que já tinha usado o sistema (o rascunho salvo no navegador era lido no formato errado) — consertado. E o painel de conversão de orçamentos passou a contar o novo “aceito” junto com o aprovado: sem isso, orçamento já fechado apareceria como vencido.
🌊 A ONDA voltou pro orçamento, na frente da gramatura. A linha da chapa agora sai "Onda BB · 657 g/m² · coluna 7 kgf". Ela tinha saído junto com o código da chapa e fez falta principalmente no corte e vinco: na maleta a onda ainda aparecia no estilo ("Maleta Normal (BB)"), mas o corte e vinco dizia só "Corte e Vinco" — o cliente não tinha como saber de que papelão era a caixa.
🏷️ Micro e papel cartão saem pelo nome deles — "Micro B", "Micro E", "Papel cartão" — sem o "Onda" na frente, que ficaria errado.
🔢 A coluna com vírgula: era "coluna 5.5 kgf" (ponto de computador), agora é "coluna 5,5 kgf".
📄 Nos quatro documentos: nota do sistema, texto do WhatsApp, app do vendedor e a folha que o cliente abre pelo link.
🤖 Agora o sistema avisa o operador sozinho — sem ninguém precisar estar olhando.
Na versão passada o sino passou a achar a etapa que ficou sem finalizar, e você mandava o recado clicando num botão. Só que o sino roda dentro do navegador: se ninguém está com o sistema aberto, ninguém vê nada — e é justamente de madrugada e no fim de turno que o operador esquece de apertar Finalizar.
👁️ Subiu uma vigia pra dentro do servidor. Ela olha a fábrica de 10 em 10 minutos, 24 horas, mesmo com o sistema fechado em todo mundo, e manda o recado no chat do operador na hora que encontra.
🔒 As travas, porque isso escreve pra uma pessoa de verdade:
• Nunca repete — cada pedido/etapa é avisado uma vez só, pra sempre. E o botão que você clica e a vigia usam a mesma porta, então o que você mandou na mão ela não manda de novo.
• Teto de 5 recados por rodada — se algum dia a regra pifar, ela erra 5 vezes, não 300. O que passar do teto volta na rodada seguinte (não some calado).
• Você manda nela. No sino, no botão ⚙, tem a chave "🤖 O sistema avisa sozinho". Desligou, volta a sair recado só quando você clica.
• O recado dela chega assinado como "PCP · aviso automático" — o operador sabe que quem escreveu foi o sistema, não você.
✅ E o "✓ já avisado" agora vale pra todo mundo: antes era só naquele computador; agora fica guardado no servidor, então você não manda duas vezes por ter aberto o sistema em outra máquina.
⚠️ Esta precisa do Luan reiniciar a API (não mexe no banco). Até ele reiniciar, o sino segue funcionando com o botão, como na versão passada.
📊 Conversão de orçamentos: quanto tem pra virar pedido, quanto já virou e quanto está escapando. A lista de orçamentos mostrava o selo de cada um, mas ninguém somava o dinheiro. Agora, logo acima da lista, aparecem 4 números:
• 💰 A converter — o que ainda pode virar pedido (pendente dentro da validade + aprovado que ainda não foi gerado);
• ✅ Virou pedido — o que já foi convertido, com quantos pedidos saíram;
• 🔴 Deixamos de converter — reprovado + o que venceu e o cliente não respondeu;
• 📊 Taxa de conversão — de cada R$ 100 já decididos, quanto virou pedido.
O botão 📊 Conversão (ao lado do "+ Novo Orçamento") abre o relatório completo: filtro de 30 dias / 90 dias / este ano / tudo, a barra do orçado no período e as quebras por cliente e por vendedor — dá pra ver quem orça muito e fecha pouco. Tem botão de imprimir.
⚡ E uma lista de "o que dá pra fazer agora", com o botão da ação do lado: o que está aprovado só esperando gerar o pedido (dinheiro parado dentro de casa), o que vence em até 7 dias e o que já venceu sem resposta — pra cobrar antes de perder.
📌 Uma explicação do número: a taxa só conta quem já foi decidido (virou pedido ou se perdeu). Hoje ela mostra 100%, porque só 1 orçamento foi decidido até agora — por isso o cartão avisa, do lado, quantos ainda estão sem resposta. Orçamento aprovado que venceu continua contando como "a converter": o prazo é do cliente responder, e ele já respondeu.
🔒 Esta tela só lê e soma — não muda status de orçamento, não gera pedido sozinho, não grava nada.
👤 Agora dá pra soltar um botão pra UMA pessoa só. Antes os botões (Criar/Editar/Excluir pedido, Etiquetas, Backup, Configurações…) eram do perfil: ligou, ligou pra todo mundo daquele perfil. Agora o 🗔 Telas de cada pessoa também tem a seção "O que esta pessoa pode fazer".
👔 O caso que pediu isso: o Túlio precisa excluir pedido e o Luan não — e os dois são PCP. Ligando no perfil, os dois ganhariam. Agora liga só no Túlio.
⚙️ Como ler a tela: os botões já vêm marcados conforme o perfil da pessoa — o que você mexer ali fica com selo +dado ou −tirado e vale só pra ela. Mexer no perfil continua valendo pra todos.
👑 E continua sem te travar: botão desmarcado no seu usuário também não tira nada de você.
🏁 O sino agora avisa quando o operador esqueceu de finalizar — e escreve o recado pra você.
É o caso do FK 35230 de hoje: a Mayara rodou as caixas e etiquetou os paletes na Grampeadeira, mas não apertou Finalizar. O pedido seguiu a vida — virou "Carregado" quando o último palete saiu do PA — e a etapa dela ficou aberta pra trás, sem ninguém ver. Nenhum dos seis alertas pegava isso: eles olham a máquina agora (parada, ajuste, ritmo), e esse é um pedido que andou pra frente deixando a etapa aberta.
🔔 Alerta novo no sino: "Grampeadeira sem finalizar", dizendo quem é o operador, quantas caixas já foram lançadas e que a produção está salva — o que falta é só fechar a etapa. Ele aparece em dois casos: quando o pedido já está em Pronto/Pronto p/ carregar/Carregado com a etapa aberta, e quando alguém encerra o turno sem finalizar tendo já batido a meta.
💬 E dentro do alerta tem o botão "Avisar <fulano> no chat". O sistema já monta o recado pronto ("a etapa da Grampeadeira do pedido X ficou sem finalizar, as N caixas estão lançadas, pega o pedido de novo e aperta Finalizar"). Você lê o texto inteiro antes, confirma, e ele cai no app do operador. Quem decide mandar é você — o sistema não fala com ninguém sozinho. Depois de enviado, o botão vira "✓ Recado enviado" e não deixa mandar duas vezes.
🤫 Por que ele não vive tocando: medi a regra no dado real antes de soltar. Solta, ela acusava 23 pedidos — e 21 eram de pedidos já entregues meses atrás, com trava pendurada que ninguém vai mais fechar. Com os três filtros (entregue fica de fora, só coisa mexida nos últimos 7 dias, e turno encerrado só conta se a meta já foi batida — encerrar turno no meio do pedido é rotina), sobraram 2 alertas, os dois de verdade. Sino que toca à toa é sino que ninguém lê.
👑 O editor de janelas agora avisa quando quem está sendo mexido é você. Desmarcar uma tela sua não tirava nada (você é o admin principal, nenhum "tirar" vale pra você) — só que a tela não dizia isso: ficava o selo vermelho −tirada e a janela continuava aparecendo. Parecia defeito, era a regra. Agora aparece um aviso amarelo no topo do editor:
• abrindo o seu próprio 🗔 Telas → "desmarcar aqui não tira nada de você — o que você marcar a mais entra normalmente";
• abrindo o perfil Admin (o seu) → "o que for tirado aqui vale pros outros usuários deste perfil — pra você, não".
O aviso só sai quando o alvo é você. Mexendo em outra pessoa ou em outro perfil, nada muda.
🔒 E a porta ficou mais firme. A pergunta "esse aí é o admin principal?" era respondida uma vez, quando a tela de Usuários abria, e a resposta ficava guardada. Se outra pessoa entrasse no mesmo computador sem recarregar, a resposta velha continuava valendo e ela conseguia abrir o editor de permissões. Agora o sistema pergunta de novo em cada ação que mexe: abrir as janelas, abrir o cadastro de perfil, salvar e apagar.
🚨 O admin principal estava perdendo telas junto com os outros — consertado. Você tirou 7 telas de custo do perfil Admin pra Luan e Túlio não verem, e perdeu as 7 também. Não era pra acontecer: a regra diz que pra você nenhum "tirar" vale.
🐛 Por que acontecia: no login o sistema monta as abas antes de saber quem você é. A pergunta "esse é o admin principal?" vai no servidor e demora um pouquinho; nesse instante a resposta ainda é "não sei", e o sistema tratava você como admin comum — aplicando as remoções. Quando a resposta chegava, ninguém remontava as abas. Todo login refazia a mesma coisa, então a tela nunca voltava.
🔧 O conserto: assim que a resposta chega, as abas são remontadas na hora. Você não espera nada — o login continua abrindo na mesma velocidade, e as suas telas aparecem sozinhas logo em seguida.
💡 O que isso quer dizer pra você: não precisa mais ficar devolvendo tela por tela no seu usuário. Pode tirar do perfil Admin o que quiser esconder dos outros — você continua vendo tudo. Se quiser limpar os ajustes que você foi fazendo em si mesmo, é o botão ↩ Padrão do perfil dentro do seu 🗔 Telas.
🔒 Agora dá pra travar os BOTÕES perigosos, não só as telas. No editor 🗔 de qualquer perfil apareceu no fim uma seção nova: "O que este perfil pode fazer". São 12 chaves — Importar relatório, Criar / Editar / Excluir pedido, Mudar status, Reordenar a produção, Exportar pro operador, Etiquetas, Configurar clientes, Configurações do sistema, Backup e Gerenciar usuários.
👔 Pra que serve: desmarcando Backup, Configurações e Gerenciar usuários no perfil Admin, os outros admins continuam vendo as telas e trabalhando normal — só não mexem no que estraga. É a trava sem tirar ninguém do lugar.
👑 E não trava você. O que você desmarcar ali continua funcionando pra você, do mesmo jeito que já era com as telas — o editor até avisa isso em amarelo quando o perfil aberto é o seu. Sem essa regra, tirar o Backup do Luan tiraria o seu junto (era exatamente o defeito que a versão passada consertou nas telas).
🟢 O que você mexer fica marcado: +dado em verde, −tirado em vermelho, igual às telas. E o Desmarcar todas / Marcar todas continua sendo só das telas — não mexe nos botões.
💸 Agora dá pra PAGAR a comissão — e o vendedor vê o que já recebeu. Até aqui a comissão era só uma conta na tela: ninguém registrava em lugar nenhum que tinha sido paga, e o vendedor via o mesmo número todo mês sem saber o que já caiu na conta dele.
1️⃣ Fechar o período (Logística → 🤝 Vendedores → 💰 Relatório de Comissões). O relatório agora mostra o mesmo dinheiro em três situações: ✅ Paga, ⏳ No financeiro (fechada, esperando a baixa) e 🟡 A fechar. No botão 💸 Fechar você confere o valor, o detalhe por cliente, escreve a referência (ex.: "Julho/2026") e o vencimento. Os pedidos daquele lote ficam carimbados e não entram em outro fechamento — pagar duas vezes o mesmo pedido virou impossível.
2️⃣ A baixa é no Financeiro, como todo o resto do dinheiro da casa: o fechamento vira uma conta em Financeiro → Contas a Pagar ("🤝 Comissão · Carlos Souza · Julho/2026"), com vencimento, entrando na previsão de caixa. Quando você dá a baixa lá, na mesma hora aparece "já pago" no app do vendedor. Desfez a baixa, volta pra "a pagar". Excluiu a conta, o fechamento é cancelado e os pedidos voltam pro "a fechar" — nunca some dos dois lados.
3️⃣ No app do vendedor, a aba 💰 Comissão ganhou ✅ Já paga e 🟡 A receber, cada cliente mostra quanto do dele já foi pago ("R$ 450,00 já pago · falta R$ 300,00") e no fim tem a lista 💸 Pagamentos: referência, valor e a data em que foi pago. O que ainda não foi pago aparece como ⏳ a pagar com o vencimento — ele para de perguntar.
🔒 O app do vendedor não enxerga o Contas a Pagar da fábrica: só chega no celular dele o que é de comissão dele. E a tabela 💸 Fechamentos de comissão, embaixo do relatório, mostra o andamento de tudo que já foi fechado.
👤 O vendedor agora tem LOGIN — um usuário curto, separado do nome completo. No cadastro (Logística → 🤝 Vendedores) apareceu o campo "Login do App (usuário)": o Carlos Souza pode entrar só como carlos. O sistema não deixa dois vendedores com o mesmo login (nem um login igual ao nome de outro), porque senão um cairia dentro da conta do outro. A lista de vendedores ganhou a coluna 👤 Login — quem ainda está sem aparece em amarelo: ⚠ sem login. Quem já entrava pelo nome continua entrando pelo nome; o login é a porta nova, ninguém fica de fora.
💰 E o vendedor passou a ver a comissão dele no app. Nova aba 💰 Comissão no App do Vendedor, com: quanto ele tem a receber no período, de quantos clientes está recebendo (ex.: "2 de 3 clientes seus") e, cliente por cliente, a % dele, quantos pedidos, o faturamento e a comissão em reais. Quem não gerou comissão aparece embaixo, com o motivo na cara: sem % cadastrada ou sem pedido no período. Dá pra filtrar por pedidos entregues ou todos e por 30 / 90 dias ou todo o período. Dentro do cartão de cada cliente também passou a mostrar "🤝 Sua comissão: 3%".
🧮 A conta é a MESMA do relatório do PCP (Logística → 💰 Relatório de Comissões): faturamento = valor × quantidade do pedido, mesma base e mesmo período. Isso é de propósito — se as duas contas divergissem, o vendedor cobraria um número que a fábrica não enxerga. A % continua morando em cada cliente (Cadastros → Clientes), porque muda conforme a negociação: mexeu lá, muda no app dele na hora.
🚚 Pedido não vira mais "Carregado" com a máquina ainda aberta. Hoje o FK GRUPO 35230 mostrou o buraco: a Mayara rodou 329 caixas e etiquetou 3 paletes na Grampeadeira, mas não apertou Finalizar. Os paletes foram bipados na expedição, o último saiu do PA e o pedido pulou sozinho pra Carregado — carregado e em produção ao mesmo tempo, e no app dela nunca aparecia como concluído. Agora, se a etapa final ainda estiver aberta com alguém, a promoção espera: aparece o aviso "⏸ FK GRUPO 35230 não virou Carregado: Grampeadeira ainda está aberta com Mayara Regis" e o pedido vira Carregado sozinho assim que ela finalizar (confere a cada 30 s, ninguém precisa lembrar de nada). A caixa sai do estoque do PA normalmente — o que espera é só o status.
Duas coisas de propósito: só a etapa final trava (uma trava velha esquecida na Slotter não pode prender a expedição), e a trava só age quando existe mesmo alguém com a etapa aberta — pedido já finalizado não tem andamento nenhum e passa direto, como sempre passou.
🪟 O perfil deixou de ser pacote fechado — agora você escolhe janela por janela. É o mesmo esquema que já roda no MTX, trazido pra cá. Em Ajustes → 👥 Usuários apareceu a barra "Janelas por perfil": clica no perfil (Admin, PCP, Visualizador, Financeiro, Desenvolvimento, Vendedor, RH) e marca/desmarca cada tela do sistema. O que você mudar em relação ao padrão fica com selo +dada (verde) ou −tirada (vermelho), pra você enxergar de bate-pronto o que foi mexido.
👤 E dá pra ajustar uma pessoa só, sem mexer no perfil dela. Cada usuário na lista ganhou o botão 🪟 Telas. Serve pro caso "o Fulano é do PCP mas também compra tinta": ele ganha a janela de compras sem virar Financeiro e sem enxergar o salário de todo mundo. O ajuste da pessoa vale por cima do perfil.
➕ Cadastro de perfil: agora você cria o seu. Botão "Novo perfil" na mesma barra. Você dá o nome (ex.: 🛒 Compras), escolhe de qual perfil ele começa igual e marca o que ele pode fazer (importar relatório, criar/editar/excluir pedido, mudar status, etiquetas, backup, usuários…). Salvou, já abre a tela das janelas pra você escolher o que ele vê — e o perfil novo aparece na lista de perfis de cada usuário.
🔒 Isso tudo é só do admin principal. Nenhum outro admin vê os botões de janelas nem o cadastro de perfil. E você (admin original) continua vendo tudo, sempre: nenhum "tirar" se aplica a você, nem por perfil nem por usuário — senão um clique errado te trancaria pra fora da sua própria tela de permissões.
🛟 Duas travas. A aba ADM nunca sai do perfil admin (é onde mora a administração). E perfil com gente dentro não se apaga: se alguém ainda está nele, o sistema mostra quem é e pede pra você mudar essas pessoas de perfil primeiro.
🐞 De quebra: criar usuário direto como RH, Vendedor ou Desenvolvimento dava "Perfil inválido" — o servidor só conhecia quatro perfis. Agora conhece todos, inclusive os que você criar. (essa parte precisa do reinício da API pelo Luan; até lá o sistema se vira sozinho.)
🐞 E o perfil RH nem gravava. Achado agora: o banco tinha uma lista fechada de perfis que não incluía o RH — quem escolhesse "👥 RH" pra alguém batia num erro do banco e o perfil não colava. A lista fechada saiu; quem confere passou a ser o sistema, que sabe dos perfis que você cria. (precisa do Luan também: rodar o banco + reiniciar.)
✅ Quem não mexer em nada não muda nada: sem ajuste salvo, cada perfil continua exatamente como sempre foi.
🙍 Cadastro de usuário por NOME — e-mail deixou de ser obrigatório. Na tela de Usuários, o campo virou "Usuário": dá pra cadastrar a pessoa como eliana e pronto. Embaixo do campo o sistema mostra como o acesso vai ficar (digitou "José da Silva", aparece entra no sistema como: jose.da.silva) — assim você já sabe o que passar pra pessoa digitar. Acento, maiúscula e espaço são arrumados sozinhos, então "Eliana" e "eliana" são sempre a mesma pessoa.
🔑 A tela de login acompanhou: o campo agora se chama Usuário e aceita nome ou e-mail. Quem já entra com e-mail continua igual, sem mudar nada.
⚠️ Um porém, pra você saber: quem é cadastrado só pelo nome não tem como usar o "Esqueci a senha" (o link vai por e-mail, e não existe e-mail). Se essa pessoa esquecer a senha, você remove o acesso dela na tela de Usuários e cadastra de novo com uma senha nova — as janelas do perfil dela continuam valendo. O próprio sistema avisa isso na tela se alguém tentar.
✅ A aba "Concluídos" do operador agora é só do turno. Ela vinha mostrando tudo o que a máquina fechou nos últimos 7 dias, então o operador abria e via um monte de pedido velho misturado com o de hoje — no quadro de hoje eram 7 pedidos do dia contra 330 de histórico. Agora cada concluído fica na lista por 18 horas e some sozinho: cobre o turno inteiro (inclusive o 2º, que vira a madrugada) e limpa antes do próximo entrar. A contagem foi feita por hora, não por "dia do calendário", de propósito — cortar na meia-noite apagaria o trabalho do turno da noite na cara de quem ainda está rodando. Nada foi apagado: o quadro compartilhado continua com o histórico inteiro (é dele que saem a Vida da Caixa e os relatórios) — mudou só o que a tela mostra. O sinal de "a etapa anterior concluiu", que solta a Coladeira/Grampeadeira, continua valendo 7 dias e não foi mexido (pedido de vários dias não pode travar na finalização).
⚖️ O orçamento não mostra mais o peso de UMA caixa — só o peso do pedido. A linha era "1,314 kg/cx · 1.314,2 kg no total". O peso por caixa é conta de fábrica (sai da gramatura × área da chapa) e, com três casas ao lado do total, parecia que eram dois pesos brigando. Agora sai só 1.314,2 kg no total. Vale em todos os orçamentos, inclusive os que já estão salvos — o documento é montado na hora, então os antigos também saem assim.
📄 Nos quatro documentos: nota do sistema, texto do WhatsApp, orçamento do app do vendedor e a folha que o cliente abre pelo link. O peso total do pedido, lá embaixo junto do total em reais, continua igual.
🎯 PERDA DE PAPEL, PARTE 2: agora a perda tem NOME. Não é mais só "a onduladeira perdeu 400 kg" — é qual pedido, qual cliente, qual onda.
🔗 E ninguém precisa apontar nada a mais. A bipagem que a empilhadeira já faz passa a dizer "este rolo está montado nesta máquina, nesta posição". Quem produziu naquela máquina enquanto o rolo esteve lá é quem comeu aquele papel. O sistema junta sozinho.
🏭 A máquina agora vem do seu cadastro (Cadastros → Máquinas), não de uma lista fixa — então Cabeçote, Facão e Integrada aparecem na bipagem junto com a Onduladeira, e a posição vale pra qualquer uma.
🪵 Montar um rolo novo avisa que o anterior saiu: "já tem rolo montado nessa posição — pese o toco dele". Com um botão que já abre o fechamento com o rolo carregado. É o momento certo de perguntar, e o único.
📋 Painel novo "🎯 Onde o papel some": por pedido, com quanto comeu, quanto virou chapa boa e a perda em kg e %, do pior pro melhor.
⚠️ E ela diz o que é: "é rateio, não medida por pedido — serve pra achar o padrão, não pra cobrar um pedido específico". Papel de rolo que não casou com nenhum pedido aparece separado como sem dono, em vez de ser empurrado pra cima de alguém.
🔍 Na Rastreabilidade, o rolo agora mostra ⚖️ "Voltou da máquina — comeu 543 kg · toco 180 kg" na linha do tempo dele.
🧹 O orçamento do cliente ficou mais limpo. Duas coisas saíram da descrição do item, a pedido do dono:
📐 A medida da chapa saiu. A linha do item mostrava "chapa 1755×1090 mm · caixa 475×375×440 mm (interna)". A medida da chapa é conta nossa — é ela que vira peso e preço aqui dentro —, o cliente confere é o interno da caixa. Agora sai só 475×375×440 mm (interna). Na tela de montar o orçamento a chapa continua aparecendo no cartão do item, que ali o PCP precisa dela.
📦 O código da chapa saiu. A linha de baixo era "ONDA BB 680 · BB · 687 g/m² · coluna 8 kgf": o "ONDA BB 680" é o nome interno do nosso cadastro, não diz nada pro cliente, e ainda repetia a onda ("BB") logo em seguida. Ficou só o que ele compra: 687 g/m² · coluna 8 kgf. Se a caixa não tiver gramatura nem coluna cadastradas, a linha do 📦 nem aparece (antes saía um "—" solto).
📄 Vale nos quatro documentos: nota do sistema, texto do WhatsApp, orçamento do app do vendedor e a folha que o cliente abre pelo link.
🧹 Últimos acertos da perda de papel — o que sobrou da revisão.
⌨️ O teclado agora sobe no tablet quando o operador toca em "SOBROU TOCO". Era a mesma pegadinha que já tinha mordido a gente antes: no iPad o teclado só aparece se o campo for focado dentro do toque, e não um instante depois. O operador ficaria olhando o campo sem conseguir digitar o peso.
❌ Servidor fora do ar parou de virar "ninguém fechou rolo nenhum". Se a tela não conseguir falar com o servidor, ela diz isso em vermelho e não mostra número — antes você poderia cobrar a equipe achando que ninguém pesou nada.
🔒 Não dá mais pra fechar o mesmo rolo duas vezes, nem quando o servidor engasga no meio. Se o fechamento gravar mas o saldo do rolo não atualizar, a tela avisa: "a perda já conta — não feche de novo, avise o PCP".
⚠️ Rolo com peso que não bate com os metros agora pede confirmação antes de fechar, mostrando a diferença — senão ele joga papel que nunca existiu direto na conta de perda.
📅 O botão "30 dias" pega 30 dias (pegava 31), e mexer só na data final parou de jogar o começo do período pra 2000.
📐 Corte e vinco: faltava a ALTURA no orçamento — e a medida da chapa não aparecia. No documento saíam só duas medidas (475×375 mm) e a altura sumia, porque o sistema cortava o ×A pra não confundir com a chapa. Só que aí sobrava uma medida de caixa pela metade, que não é medida de nada. Agora o item de corte e vinco sai assim: chapa 1000×700 mm · caixa 475×375×440 mm (interna) — primeiro a medida da chapa, que é a que manda no orçamento (é ela que vira peso e preço), e junto a medida da caixa marcada como interna, que é o que o cliente quer conferir. Maleta continua igual (C×L×A), que lá a chapa é calculada.
📄 Vale nos quatro documentos. A nota do sistema, o texto do WhatsApp, o orçamento do app do vendedor e a folha que o cliente abre pelo link — os quatro passaram a escrever a mesma coisa. O app do vendedor ainda ganhou a medida final da chapa (já com o refile): antes ele nem recebia esse número e imprimiria uma chapa menor que a de verdade.
🖥️ A tela de montar o orçamento também estava trocada. A caixinha de resultado tem o rótulo "Chapa (C × L)" mas mostrava o número ao contrário, L × C — quem conferia com a régua achava que a chapa tinha sido cadastrada invertida. E o cartão do item, na lista, mostrava só "chapa 905×1240" (também invertido, e com a medida digitada, sem o refile). Agora tela e documento falam igual: C × L na chapa, C × L × A na caixa.
📏 A medida da chapa passou a ser C × L no sistema inteiro. Também na coluna "Medida chapa" da Carteira (PCP) e na coluna "Medidas chapa" da lista de Cadastros → Caixas, que mostravam largura primeiro. Isso desfaz o que a v2.24.1 (05/06/2026) tinha combinado — lá a chapa mostrava largura × comprimento de propósito nas listas. Se a fábrica lê a chapa por largura, é só avisar que eu volto. O Micro/Cartão, o romaneio e o laudo já eram C × L.
📅 Cronograma: pedido PRONTO parou de comer a máquina, e quem não cabe no dia agora aparece. Dois irmãos do problema de ontem, os dois deixavam a raia mentindo.
1) Pedido já pronto ocupando a máquina. O JESSE ASSADOS VERMELHO acabou hoje nas duas máquinas (Slotter 10.770 cx às 08:50 com o Miller · Coladeira 10.773 cx às 11:17 com o Mirailton) e ainda saiu etiquetado. Só que, quando o operador finaliza, o app apaga o andamento da etapa — e como o ajuste de meta (15.000 → 10.773, o resto virou pedido novo) também tinha limpado as etapas do pedido, o cronograma ficou sem nenhum sinal de que aquilo tinha acabado: tratou como se fosse rodar ainda, com a quantidade VELHA de 15.000, e a barra dele comeu a Slotter até 23:28, empurrando três pedidos do FK pra madrugada. O contador ainda dizia "0 concluídos" com as duas máquinas fechadas. Agora, pedido em Pronto / Pronto p/ carregar / Carregado / Entregue conta como concluído em todas as etapas — as caixas que ele fez continuam vindo dos lançamentos.
2) "Não cabe mais hoje" nunca aparecia. Quando um pedido entra depois do plano do dia já congelado e não sobra tempo na máquina dele, o cartão tem um aviso "🌙 Não cabe mais hoje — entra na fila de <dia>". Esse aviso nunca chegou a aparecer: o pedido era descartado antes. Hoje mesmo eram 3 pedidos invisíveis — VIVIMAR CX 02 (8.500 cx), TANGARA CX 10 DETERGENTE (10.000 cx) e KININO 01 (30.000 cx). Agora eles aparecem no dia com o aviso, sem barra e sem ocupar máquina nenhuma (e sem entrar na conta de "% das caixas" do turno, que é só do que roda hoje).
📅 Pedido com material disponível sumia do cronograma — culpa de 3 minutos. Hoje (10/08) o operador começou o ajuste do JESSE ASSADOS VERMELHO na Slotter às 04:57, três minutos antes do turno abrir (05:00). Como a Slotter vira a noite (vai até 01:36), o cronograma achou que 04:57 era a madrugada do dia seguinte e jogou esse pedido pra 28:57 — quase 24 horas pra frente. A partir dali, a raia inteira da Slotter foi empurrada pra depois do fim do turno: as barras encolheram pra zero e os pedidos desapareceram da tela, mesmo estando no plano. Era por isso que o JESSE ASSADOS e os 4 pedidos do FK GRUPO (35230, 04141, 39869, 35600) apareciam como Material disponível na carteira e não apareciam no cronograma. Agora só conta como madrugada o horário que está mesmo dentro do rabo da noite (até 01:36) — começar cedo não desloca mais nada, e os 5 pedidos voltaram pra raia da Slotter no horário deles.
📦 Caixa que vai ABERTA: a onda agora conta 1 vez, não 2 — cabia o dobro no palete e a tela escondia isso. Quando você marca 📏 CAIXA VAI ABERTA, a caixa sai plana, sem colar: cada uma tem uma espessura de onda, não duas. O desenho do palete já sabia disso, mas a sugestão escrita logo acima dele continuava multiplicando por 2 — e é ela que você lê. No exemplo da tela (25 cx por amarrado, onda B de 3 mm): ela dizia pacote de 150 mm → 7 camadas → 350 caixas/palete, quando o certo é 75 mm → 14 camadas → 700 caixas/palete. Metade do palete. Agora a linha mostra "× 1 (vai aberta — não dobra)" e a conta bate com o desenho.
🧾 O mesmo erro estava na ficha do operador e na entrada do estoque. O ✓ de caixa aberta fica guardado dentro da caixa, e essas telas não liam ele: a ficha de paletização mandava montar palete com metade das camadas. Agora leem.
🧱 A lateral do pacote sumia no desenho 3D do palete. Nos recortes do canto da faca, a parede do amarrado virava serrote e dava pra ver o fundo entre uma camada e outra — o palete parecia um monte de folha solta flutuando. Era o preenchimento do desenho se anulando sozinho (os retalhos da lateral saíam metade num sentido, metade no outro). Agora a lateral sai inteira, de cima a baixo.
🔧 RH, DRE e Conciliação de volta ao menu. As telas entraram na v2.37.244, mas as abas e os espaços delas sumiram do miolo da página nas v2.37.250–252 (o arquivo foi sobrescrito por outra frente de trabalho); a v2.37.253 devolveu só metade do conserto. Agora o módulo 👥 RH volta a aparecer no menu, e o Custos volta a ter as abas 📑 DRE e 🏦 Conciliação.
🔌 As abas 👥 RH, 📑 DRE e 🏦 Conciliação agora abrem DENTRO do sistema. Elas existiam desde a v2.37.244, mas o código delas nunca era carregado pela página — clicava e vinha tela vazia. Agora carrega: Fichas, Escala da equipe e Ponto no módulo RH; DRE e Conciliação no módulo Custos. Os apps de celular (RH, Ponto, DRE, Conciliação) continuam iguais — é a mesma informação nos dois lugares.
🔎 A conta de perda de papel ia te dar número errado — 29 defeitos achados por revisão automática, antes de você confiar nela. Os graves:
✂️ A conta esquecia os CORTES. A onduladeira faz uma passada e saem 2, 3, 4 peças lado a lado — a conta usava só uma. Num pedido de 20.000 caixas com 2 cortes, a chapa boa saía 3.139 kg em vez de 6.279 kg, e uma perda de ~2% aparecia como 50% em vermelho. Agora bate na vírgula.
📅 Ela ignorava 155 dos 157 pedidos. A conta procurava a data em que a chapa saiu — um campo que só 2 pedidos têm (o campo de chapa do PCP não carimba). Resultado: "chapa boa ≈ zero" e perda de 100%, confiante. Agora ela procura a data em escada: chapa → lançamento → apontamento de produção, e diz quando usou a data de segunda mão.
📄 Papel apagado do cadastro sumia da conta calado. Uma chapa BB com 1 papel órfão entrava 20% mais leve — 2 toneladas de perda inventada, sem uma palavra. Agora aparece no rodapé.
🛑 E o aviso de "não confio nessa conta" cobria só metade dos casos. Pegava "saiu mais chapa do que papel", mas não o caso que a fábrica vive: cadastro incompleto fazendo a perda parecer maior. Agora, se mais de 20% dos pedidos do período estiverem capengas, a tela mostra "?" e diz exatamente o que consertar.
⚖️ No app de bobinas: não dá mais pra fechar o mesmo rolo duas vezes (contava o consumo em dobro); rolo sem peso cadastrado não fecha (gravaria "comeu 0 kg"); e o toco parou de acusar falso "peso e metros não fecham" toda vez que era lido de novo.
🕐 As datas agora são do relógio daqui, não de Londres — rolo fechado depois das 21h caía no dia seguinte.
📊 A cobertura passou a existir de verdade (ela lia uma lista que eu tinha inventado): "40% — 2 de 5 rolos voltaram fechados. Faltam 3 — enquanto isso a perda aparece MENOR do que é."
📄 PERDA DE PAPEL — a primeira conta em kg e R$ da história da fábrica. Você disse que é onde mais se perde e é onde quer atacar. Esta é a parte 1.
⚖️ No app de bobinas tem a aba nova "🔙 Voltou da máquina". O operador lê o QR do rolo e é um toque: ACABOU (foi tudo) ou SOBROU TOCO + o peso da balança. O toco volta pro estoque já com o peso e os metros novos, pronto pra rodar de novo.
🎯 Por que só isso resolve: hoje o sistema desconta o papel pelo que a produção deveria ter gastado — então o toco calculado sempre bate e a perda dá zero por construção. O único número que ninguém tem é quanto sobrou. E repare: não é "apontar perda", é pesar o toco — o operador não está confessando nada.
📊 Tela nova em Análises → 📄 Perda de Papel: papel que a máquina comeu (medido) × o que virou chapa boa (calculado papel a papel) − refile de projeto = a perda, em kg e em R$. Por período e por máquina.
🧪 A conta não mente por descuido: a chapa boa é calculada sem os 15 g/m² de cola (cola não vem de bobina — usar ela esconderia ~3% da perda), e se sair mais chapa do que papel medido a tela avisa que a conta não fecha em vez de mostrar "perda 0" e te fazer achar que está tudo bem.
🧻 De brinde: agora existe como apagar bobina (as duas primeiras do sistema, de teste, diziam 1.000 kg mas os metros davam 288 e 216 — 2.000 kg fantasma). A rota já subiu; falta o Luan reiniciar o servidor.
Parte 2 (o elo automático rolo→máquina→pedido) e a entrada da perda de papel no Perda por Etapa vêm em seguida.
🔗 RH virou a fonte da verdade dos funcionários. Reajustou o salário (ou função, setor, situação) na ficha do RH — no sistema ou no app do celular — e o Custos atualiza sozinho: nada de digitar em dois lugares. Ficha nova com salário já vira funcionário no Custos (encargo ×1,68 padrão).
O que só existe no Custos fica intacto: encargo, benefícios e o funcionário PJ continuam sendo ajustados lá, e ninguém é apagado pela sincronização. Primeira vez? Use "Puxar do Ponto / Custos / Operadores" na tela de Fichas pra trazer a equipe atual — daí em diante é automático.
🔪 O FACÃO AGORA RODA DE PONTA A PONTA. Uma revisão automática simulou o caminho inteiro (PCP → programação → cabeçote → operador → etiqueta) e achou que ele travava em dois pontos. Os dois estão consertados:
⛔ O operador do Facão nunca conseguia começar. O pedido nascia com uma etapa fantasma "impressora" na frente, e o app ficava em "⏳ AGUARDANDO FACÃO 01" — esperando ele mesmo, pra sempre (ninguém conclui essa etapa, porque o cabeçote lança no app da onduladeira). Agora a rota do facão é uma máquina só, e ele inicia direto.
⛔ O pedido nunca virava "Pronto". Quem fecha o pedido só conhecia coladeira e grampeadeira — então a folha não gerava etiqueta, não entrava no Estoque PA e a Expedição nunca via o palete. Agora qualquer máquina de Fechamento do seu cadastro fecha o pedido.
📦 A ficha de paletização chega no operador do Facão. Ele recebia a ficha de CAIXA (arte, clichê, faca, vinco); agora recebe lastro, amarrado, folhas por palete e filme — a ficha que a gente criou na v2.37.243 e que não estava chegando nele.
🔢 Conta de folhas corrigida no cabeçote. A meta, o "Folhas", o "Papel kg" e a baixa de bobina saíam divididos pelos cortes (com 4 cortes, ¼ do certo) e o ✅ de "meta batida" mentia. O pedido do facão já é em folhas — não se divide de novo. E no modo ✏️ Corrigir a bobina era descontada duas vezes.
💰 E o preço da folha parou de sumir: depois de corrigir um valor na mão, a próxima folha nascia sem preço — a trava ficava ligada pra sempre. Agora ela é por ficha.
Foram 19 defeitos confirmados pela revisão; estes são os que impediam o setor de funcionar. O resto vem em seguida.
🤝 Funcionário PJ entra pelo valor pago, sem encargo. Botão novo roxo "➕ Adicionar PJ" em Custos → Fixos & Funcionários: PJ não leva ×1,68 nem benefícios — o custo é exatamente o valor que você paga. Na tabela ele aparece com o selo PJ. O DRE e o custo-hora do Ponto também respeitam a regra.
✏️ Agora dá pra editar funcionário. Lápis em cada linha: corrige salário, função, encargo, benefícios e setor sem precisar apagar e cadastrar de novo.
📈 A comissão dos vendedores entrou no Ponto de Equilíbrio. A % de comissão de cada cliente (do cadastro de Clientes, quando tem vendedor vinculado) agora é descontada como custo que acompanha a venda — o "pra empatar" e o lucro do mês ficaram mais honestos. A tela mostra quanto foi a comissão do mês.
🔎 Mais quatro defeitos do Facão, achados por revisão automática antes de o primeiro pedido rodar:
💣 O botão "Corrigir valores" ia multiplicar a folha por 1000. Ele trata todo preço abaixo de R$ 0,50 como erro de importação — mas a folha de micro custa R$ 0,257 de verdade. Um clique e ela viraria R$ 257,00 por folha, sem desfazer. Agora micro/cartão fica de fora, o aviso diz quantos ficaram, e a confirmação avisa que não tem desfazer.
📉 O Perda por Etapa sumia com os pedidos do facão. O relatório multiplicava as folhas pelos cortes — mas o cabeçote já lança em folhas (a conversão dos metros já multiplicou). A base dobrava, batia na trava de "aponta mais do que entrou" e o pedido saía do relatório pra sempre. Agora fecha certo.
🏭 A perda do facão não era de ninguém: Facão 01, Cabeçote 01 e Integrada 01 caíam em "❓ Não informado" e o motivo apontado pelo operador não grudava no degrau. Agora têm setor próprio: 🔪 Facão.
🧩 O 1º degrau do funil agora diz "Cabeçote" nos pedidos de folha (era "Onduladeira", máquina que não rodou o serviço).
🩹 E um erro meu na ficha do Micro: o campo "Folhas por amarrado" tinha aparecido duas vezes; o de baixo era morto — não calculava o palete nem salvava. Ficou um só, no lugar certo.
👁️ "Quem abriu os links" — botão novo no Desenvolvimento. Uma tela só com todos os links já enviados: quem abriu, de que aparelho, de que IP e quando. E, o principal, quais o cliente nunca abriu — esses ficam em vermelho, com há quantos dias o link foi mandado.
📋 Também entra no histórico da proposta, junto com as aprovações: "cliente abriu o link — iPhone · Safari · IP … · aparelho ap_…".
🔁 Não enche o histórico: o portal recarrega sozinho depois de cada aprovação, então abertura igual do mesmo aparelho só é anotada uma vez a cada 6 horas. E abrir o link nunca dispara e-mail.
⚠️ Não é o MAC — e nunca vai ser. Navegador nenhum entrega o endereço da placa de rede, em aparelho nenhum; o app do operador também não pega. O que dá é tipo do aparelho + navegador + IP + hora, mais um código ap_… que diz "é o mesmo aparelho de antes" e muda se o cliente limpar o navegador.
👥 Módulo RH dentro do sistema. Ficha completa do funcionário (documentos, férias, ASO e EPIs — com alerta automático do que está vencendo pela CLT), escala da equipe (T1/T2/folga, 🏖️ férias automáticas, ✗ FALTOU cruzando com o ponto) e espelho de ponto com importação do arquivo do relógio (AFD, Portaria 671). Importar o mesmo arquivo duas vezes não duplica nada — nem aqui, nem no app do celular.
📑 DRE — o resultado do mês sem digitar nada de novo. Aba nova no módulo Custos: receita pelas notas importadas, custos variáveis e fixos que o Centro de Custos já conhece, margem de contribuição e o resultado, mês a mês e no ano. Só leitura.
🏦 Conciliação bancária. Importa o extrato do banco (OFX ou CSV), casa cada linha com a conta em aberto do Contas & Previsão (mesmo valor, vencimento perto) e dá baixa com um clique — a conta some dos "em aberto" na hora. Reimportar o mesmo período não duplica (identificador do banco).
📱 Ponto e RH também no celular. Os apps painel_ponto e painel_rh entraram no menu de apps (aba ADM) — são exatamente os mesmos dados das telas novas.
Quem vê: salário é dado sensível — as telas novas aparecem só pra admin e financeiro. O perfil novo "RH" vê as telas de gente sem ver custo nenhum. O espelho de ponto é gerencial; o AFD do relógio continua sendo o registro legal. Por baixo do capô: migrations 025–027 + rotas /api/ponto, /api/rh e /api/fin (precisam do Luan: migrate + restart — até lá as telas funcionam normal pelos snapshots). Veio do MTX com autorização, testado lá com 7/7 critérios de aceite.
🔪 O Facão virou opção de FECHAMENTO de verdade — e parou de aparecer "fora do cadastro". Tres coisas que voce pegou testando:
⚠️ "Facão — fora do cadastro": voce cadastrou Facão 01, mas o pedido nascia apontando pro nome chutado "Facão". Nome que não bate com o cadastro é máquina órfã — o pedido some do app do operador. Agora a folha usa a máquina de Fechamento que existe no seu cadastro, pelo nome certo.
✅ Faltava o Facão na lista de finalização: a 2ª máquina só oferecia Coladeira e Grampeadeira. Agora toda máquina cadastrada como "Fechamento (etapa final)" aparece lá — Facão 01, Integrada 01 e as que voce criar.
📦 A ficha do Micro ganhou a Paletização, como no cadastro da caixa: palete, altura, folhas por amarrado, lastro e filme — com a conta ao vivo: "5.000 folhas por palete = 4 pacotes × 5 camadas × 250 folhas · ≈ 194,6 kg". A folha entra plana (sem dobra), por isso cabe mais que caixa.
👁️ E o Facão não aparece mais duas vezes no roteiro: como ele corta e já fecha o palete, agora sai uma vez só, em verde, com a explicação "corta e fecha o palete aqui".
🏭 Na ficha, as máquinas vêm do seu cadastro — nada de nome fixo. Se ainda não cadastrou nenhuma de Fechamento, ela avisa onde cadastrar.
💰 O preço agora anda sozinho do cadastro até o pedido. Faltavam dois pulos:
1️⃣ Na ficha do Micro / Cartão, o R$/kg vem da chapa. Se a chapa tem "R$/kg nominal" (ex.: 6,60), a ficha já abre com ele e calcula o valor da folha. Fechou diferente com o cliente? é só digitar — e a ficha avisa embaixo: "nominal da chapa: R$ 6,60/kg (10,6% abaixo)", pra você ver na hora que está vendendo abaixo da referência.
2️⃣ No "+ Novo Pedido", o Valor unit. vem do cadastro. Escolher o produto já trazia código, roteiro e velocidade, mas o valor ficava 0,00 e alguém tinha que digitar de novo (ou esquecia, e o pedido seguia pro faturamento valendo nada). Agora preenche sozinho e mostra ✓ preço do cadastro embaixo do campo.
🔒 O que você digitou não se perde: o preenchimento automático só acontece com o campo vazio — valor já digitado é decisão sua e o sistema não encosta.
Vale pra caixa também, não só pro micro.
🧩 Escolher "Micro" ou "Facão" no cadastro agora dá exatamente no mesmo — como já parecia dar. As duas opções dizem "folha", mas o resto do sistema só reconhecia Facão: uma folha salva como Micro ia sair com a medida "—" no romaneio, sem a linha "Medida da folha" na etiqueta do palete e com riscador na programação — tudo calado. Agora, sempre que o cadastro for folha, ele é gravado como Facão.
Nada do que já está cadastrado mudou (não havia nenhum micro na base). Achado pela mesma revisão automática, que fechou com 23 achados — 7 reais, todos corrigidos.
🔎 Cinco defeitos do cadastro de Micro / Cartão, achados por uma revisão automática antes de a fábrica usar:
💰 O preço corrigido na mão agora SEGURA. Você digitava R$ 0,300 no lugar do calculado 0,214 e salvava — mas ao reabrir a ficha (ou só mexer na medida) o sistema jogava 0,214 por cima, calado. O preço combinado com o cliente sumia.
🏷️ E o preço vai pro campo certo: numa folha que já tinha "preço unitário" salvo, sua correção era engolida — a tela e o Centro de Custo continuavam com o preço velho.
🏭 A máquina não some mais. A ficha só conhecia Facão e Integrada: se a folha estivesse apontada pra outra máquina, bastava abrir e salvar pra ela virar "Facão" sem ninguém ver. Agora as opções vêm do Cadastro de Máquinas e a que não está lá aparece como ⚠️ (fora do cadastro), preservada.
📦 Caixa de verdade em micro-ondulado voltou a ser possível. Escolher uma chapa de micro transformava QUALQUER cadastro em folha — apagava o modelo e a caixa sumia da lista de Caixas. Agora, se o setor diz Cartonagem ou Chapa, ele manda: micro vira folha só no Facão/Micro.
🗑️ Excluir agora apaga DE VERDADE. A exclusão só apagava no aparelho e o item voltava no próximo sync (vale pra caixa também, não só pro micro). Agora avisa o servidor; se ele recusar, a tela diz em vermelho em vez de fingir que apagou.
👆 E a ficha do micro fecha clicando no fundo escuro, como todas as outras.
🗑️ O ✕ do Micro / Cartão estava morto — agora exclui de verdade. Na tela nova, clicar no ✕ da linha não fazia nada: nem apagava, nem avisava, nem dava erro (o código chamava uma função que não existia, escondida atrás de uma checagem). Agora abre a mesma confirmação da caixa e apaga de verdade, salvando no servidor.
🏷️ E a confirmação fala a língua certa: dizia "Excluir esta caixa?" mesmo quando era um micro. Agora diz "Excluir este micro / cartão?".
Achado por uma revisão automática do código feita antes de a fábrica usar.
🔪 O MICRO / CARTÃO ganhou o cadastro dele — separado da caixa. Decisão do dono: "tem o de caixa e tem o de micro, assim fica separado as coisas". Agora tem Cadastros → 🔪 Micro / Cartão, com lista, busca por cliente e o botão ➕ Novo Micro / Cartão.
📋 A ficha do micro é curta e só do micro: cliente, referência, chapa (só aparecem as de Micro B, Micro E e Papel cartão), medida da folha C × L, preço e a máquina (Facão ou Integrada). Não tem altura, modelo, vinco, riscador, clichê, faca, cores nem tinta — nada que é de caixa.
👥 Como vincula no cliente: exatamente igual à caixa — o campo Cliente, no topo da ficha. Ele avisa em verde "✓ cliente cadastrado" e, se for cliente novo, tem link pra cadastrar na hora. É esse vínculo que faz o pedido achar o micro certo (nunca cruza cliente).
⚖️ Peso e valor saem do m² na hora: digitou 400 × 350 numa chapa Micro E de 278 g → área 0,1400 m², peso 0,039 kg e o valor pelo R$/kg, com o R$/m² do lado.
📦 Cada lista mostra só o que é dela: a tela de Caixas não mostra mais micro/cartão, e a de Micro não mostra caixa. O que já estava cadastrado como Micro ou Facão aparece sozinho na tela nova.
🩹 E o cadastro antigo, pelo modal da caixa, parou de pedir coisa de caixa: quem escolhia setor "🧩 Micro" continuava vendo Altura, modelo e riscador (só o "🔪 Facão" escondia). Agora Micro, Facão e a própria chapa de micro/cartão ligam o modo folha.
⌨️ A IA "Pergunte ao sistema" voltou a abrir o teclado no tablet e no celular. O anel colorido em volta do campo era um enfeite invisível que cobria o campo inteiro — no computador ninguém percebia (o campo já abre focado e o teclado físico digita direto), mas no tablet/celular o toque batia no enfeite em vez do campo, e o teclado de tela nunca subia. Agora o toque atravessa o enfeite e cai no campo.
📱 E ao tocar no 🤖 pra abrir a IA, o teclado já sobe junto — no iPad/iPhone o teclado só aparece se o foco acontecer na hora exata do toque; o sistema agora foca o campo nesse instante.
🔪 Cadastro de FOLHA do facão — no mesmo lugar da caixa, vinculado no cliente. Escolheu o setor 🔪 Facão no cadastro, o formulário vira o de folha: some medida interna C×L×A, modelo, vinco, compensação, clichê/faca — fica só cliente + referência + chapa de micro/cartão + C×L da folha.
📐 Peso e valor saem do m², ao vivo: digitou 350×400 com chapa Micro E 278 g → a tela mostra na hora 0,14 m² · 0,039 kg · e o valor pelo R$/kg. Ex. do dono conferido: micro onda E 280 g 350×400.
🏭 Máquina escolhida ali mesmo: Facão (padrão) ou Integrada — o pedido nasce certo pra fila do cabeçote e pro operador.
📦 Palete de folha honesto: a folha vai PLANA (1 espessura, não ×2 da caixa colada) e a peça do palete é a folha inteira — a sugestão saía pela metade e com refile fantasma de 30 mm. O app do operador também aprendeu a espessura do micro (a sugestão dele ficava muda).
🏷️ Documentos com a medida certa: etiqueta de palete ("Medida da folha: 400×350" — no sistema e no app do operador), romaneio ("folha 400×350 mm") e laudo de qualidade (imprimia "? × ? × ?" pra folha).
📋 Na lista de caixas, a folha aparece com selo 🔪 FOLHA e a onda com nome bonito (Micro E, não "microE"). Pedido de folha se lança pelo "+ Novo Pedido" de sempre.
👁 O "continuar o mesmo pedido" parou de deixar a Perda por Etapa cega. Quando um pedido parcial continuava, a chapa da rodada anterior era zerada pra lançar a do saldo — e a história se perdia: o funil somava a produção das DUAS rodadas mas só via a chapa de UMA, e acusava um falso "aponta mais do que entrou" (caso do 23707: +4.946 que não existia).
💾 Agora a chapa da rodada que fechou fica guardada (nas duas portas: decisão do PCP e sinal do operador) e a Perda por Etapa soma tudo — pro 23707 do futuro, o funil mostraria a perda real de ~146 caixas em vez do falso excesso. A Vida da Caixa também passa a mostrar a chapa total das rodadas. Vários "continuar" no mesmo pedido acumulam certinho.
🔢 No Mutirão, digitar a chapa certa zera o acumulado — o número que você digita é a verdade inteira (todas as rodadas), então nada soma em dobro depois. Os pedidos antigos que já perderam a história (23707, 23611, 23748) continuam na lista do Mutirão pra você completar o número — dado deles não foi mexido.
📉 O "reprogramar" parou de somar o saldo por cima da compra. Quando o PCP reprogramava a diferença de um pedido parcial, o pedido original continuava valendo a compra cheia (10.500) E ainda nascia o pedido novo com o saldo (5.062) — a carteira via 15.562 numa compra de 10.500 e o rodapé mostrava "Falta: -2.597". Agora, ao reprogramar, o pedido original passa a valer o que produziu de verdade (5.438) e o saldo vai pro pedido novo — original + novo = a compra certa. O total antigo fica guardado na vida do pedido ("Meta ajustada: 10.500 → 5.438").
🧾 Os pares antigos que vieram do relatório do Sectra (tipo o 23611 da TANGARA, que já estão no banco — nenhum dado foi mexido) também pararam de contar em dobro: quando o pedido cheio e o saldo aparecem na mesma lista, o rodapé do PCP e do Relatório soma a compra uma vez só — em caixas e em R$ (o valor também dobrava).
📦 "Falta" negativo não existe mais: quando a fábrica produz além da compra, o rodapé agora diz o que aconteceu — "A mais (foi pra estoque): 7.659 caixas", em âmbar — em vez de um "Falta: -2.597" que parecia conta errada.
📏 O cabeçote lança em METROS, não em chapas. O dono explicou: o cabeçote não entrega chapa — entrega bobina de micro, que o Facão recebe pra cortar. No bloco 🧩 do app da onduladeira, o lançamento do micro agora pede os metros de bobina que saíram e converte sozinho em folhas pro Facão (mostra a conta na tela: "800 m ≈ 2.000 folhas").
🧩 O bloco virou "Cabeçote / Integrada — 1ª etapa": a Integrada tem 2 etapas — na 1ª entram os papéis (é este bloco, igual à onduladeira) e na 2ª o micro é contado pelo operador dela no app do operador, com palete e etiqueta.
🧾 Os metros lançados ficam guardados no pedido (histórico rodada a rodada) — é a base pra no futuro a bobina de micro ter etiqueta própria com QR.
🔁 Pedido que volta reprogramado agora conta a história inteira no PCP. Pedido partido (fez uma parte, o resto voltou pra fila) aparecia só com o número quebrado — "5.062 cx" — e ninguém sabia de onde ele veio. Agora o cartão mostra o pedido total em cima ("📦 10.500 cx no total") e, embaixo do campo da chapa, o selo roxo 🔁 reprogramado · fez 5.438 · falta 5.062.
🧠 Como o sistema sabe: o saldo que o relatório do Sectra manda (mesmo número, MESMA caixa) é casado com o pedido irmão — e o selo só aparece se a conta fecha (total = feito + saldo). Entrega parcelada de verdade (dois pedidos independentes) não ganha selo, e caixa diferente nunca cruza. Pedido reprogramado pelo caminho "continuar o mesmo pedido" também mostra, com o feito/falta calculado ao vivo pelos registros.
Nasceu da conferência dos pedidos 23611, 23748 e 23707 da TANGARA no Mutirão da Perda por Etapa. Nenhum número de produção mudou — é só o cartão que passou a explicar.
🔪 FACÃO, parte 3: o cabeçote e o operador — nos apps que já existem. O dono confirmou: o processo do cabeçote é igual ao da onduladeira (junta os papéis da bobina → gera a bobina de micro). Então nada de app novo pra decorar:
🧩 App da onduladeira ganhou o bloco "CABEÇOTE — bobina de micro" (em verde, embaixo da fila normal): os pedidos de micro/cartão programados aparecem ali, com bobina, metros, papéis, conferência de bobina por QR e o "produziu" — tudo igual à onduladeira. Cada máquina enxerga o seu bloco.
👷 O Facão é máquina de FINALIZAÇÃO — corta e vai direto pro palete. O operador dele usa o app do operador de sempre, com o fluxo completo da coladeira: corta as folhas, lança a produção, fecha os paletes e imprime as etiquetas. O pedido de micro nasce com a máquina Facão (ou Integrada, se escolhida no cadastro da caixa).
⚖️ O rateio de kg por papel no app da onduladeira agora usa a % da onda do cadastro (B 35% · E 25% · editável no sistema) — era 35% fixo pra toda onda; o miolo do micro E sairia 10% mais pesado.
‼️ O passo do cadastro (corrige o que a versão anterior ensinou): em Cadastros → Máquinas, cadastre Cabeçote como 🔪 Corte / preparação (ele prepara a bobina de micro) e Facão e Integrada como ✅ Fechamento (etapa final) — é o Fechamento que liga a paletização e as etiquetas pro operador. Depois, marque a máquina Facão/Integrada nos operadores dela (modal Operadores — as máquinas cadastradas viram opção sozinhas).
🔪 FACÃO, parte 2: a programação — na mesma tela de sempre. Quem programa chapa e micro é a mesma pessoa, então o pedido de micro/cartão entra na MESMA Programação do PCP, com o selo 🔪 facão.
📦 Pedido de micro se lança igual pedido de caixa: cadastre o produto (chapa Micro B/E ou Papel cartão + caixa no setor Facão) e lance pelo "+ Novo Pedido" de sempre. O pedido já nasce com a máquina Cabeçote (a que prepara a bobina de micro — ou a que você escolher no cadastro da caixa, ex.: Integrada) e sem etapa de colagem — folha não dobra nem cola.
📐 Sem vinco no facão: ao programar um pedido do facão, o modal mostra "folha lisa" — só a medida da folha, sem riscador.
📏 A máquina agora é de 1600 mm, não 1500. O sistema tinha um teto de 1500 mm que era do código, não da fábrica — onduladeira, facão e integrada são todas de 1600 (confirmado pelo dono). Programas que "não cabiam" por 100 mm agora cabem.
🧻 Bobinas 1040 e 1370 entraram na lista — existem 18 delas no estoque real e a lista só oferecia múltiplos de 50 (o PCP escolhia "1050" pra uma bobina que é 1040). E entraram 1550 e 1600 pro teto novo.
🧵 Na fila, o facão tem grupo separado (em verde, marcado FACÃO), depois das ondas da onduladeira — e o app da onduladeira NÃO mostra pedido do facão: é fila de outra máquina.
⚠️ Pra fechar: cadastre as 3 máquinas em Cadastros → Máquinas, cada uma na posição certa (o dono confirmou): Cabeçote = 🔪 Corte / preparação (junta os 2 papéis, gera a bobina de micro) · Facão = ✅ Fechamento (corta a folha e entrega o palete pronto) · Integrada = ✅ Fechamento (faz as duas coisas numa passada só). Sem isso o pedido do facão fica com máquina fora do cadastro e ninguém vê. O app do operador do facão (palete + etiqueta) é a próxima parte.
🔪 Começou o setor FACÃO — esta é a primeira parte: o material. Agora dá pra cadastrar o que o facão usa, que a chapa normal não comporta.
🧩 Micro é 2 papéis, não 3. Na tela de Chapas apareceram Micro B e Micro E, que pedem só capa + miolo. Antes toda chapa obrigava 3 papéis, então micro não tinha como ser cadastrado direito.
📄 Papel cartão é 1 papel só. Também entrou na lista de ondas e pede um papel só, sem miolo.
〰️ A % da onda virou campo que você edita (Orçamento → Configurações → Compensações por onda). O sistema usava 35% fixo pra toda onda; agora onda B usa 35% e onda E usa 25%, como é na prática. Mudou a %, o cadastro de chapa e a Programação passam a usar o valor novo (chapa já salva só recalcula quando for salva de novo; o app da onduladeira acompanha na próxima fase). E digitar 0% numa onda com miolo o sistema recusa — miolo sem acréscimo não existe.
✅ Nada do que já roda mudou de número: as 20 chapas cadastradas são todas B e BB, que continuam nos 35%. A ONDA B 404 continua 404 g/m².
🏭 O setor 🔪 Facão já pode ser escolhido no cadastro da caixa e no cadastro de encarregado.
Vem depois: a programação do facão (bobina, cortes e metro linear na máquina dele) e o app do operador do facão, com palete e etiqueta.
⚠️ O app da onduladeira agora avisa em vermelho quando falta cadastro. Antes, se a caixa não tinha chapa ou a chapa estava sem papel, o card mostrava "0 g/m²" e "0 kg" como se fosse número bom — e o operador rodava confiando nisso.
🚨 Faixa vermelha no topo do card: "FALTA CADASTRO — NÃO CONFIE NOS NÚMEROS DESTE CARD", dizendo o que está faltando (caixa sem chapa, camada sem papel ou gramatura zerada).
📄 A linha do papel que falta fica vermelha com "⚠ PAPEL NÃO CADASTRADO" e "? kg" no lugar do zero. Isso importa porque o peso do papel que falta era jogado em cima dos outros: numa caixa de 3 papéis, as capas apareciam com 116 kg em vez de 69.
🧻 A conferência da bobina parou de mentir. Sem papel cadastrado ela era pulada e QUALQUER bobina lida dava ✅ verde, mesmo sendo o papel errado. Agora avisa "não dá pra conferir a gramatura".
✅ Pedido com cadastro completo continua exatamente igual — nenhum aviso novo aparece.
🏷️ Imprimiu a etiqueta, o pedido vira "Pronto p/ carregar" — em todos os computadores. Antes o pedido era impresso numa máquina e continuava "Pronto" nas outras: quem estava no outro PC não sabia que o palete já podia ir pra expedição e mandava imprimir de novo.
🔄 Não importa quem imprimiu. A marca de "já imprimi" já era compartilhada; agora o pedido anda junto e o status sincroniza sozinho.
🛡️ Três travas: só sai de Pronto (nunca de pedido em produção, nem de quem já foi carregado ou entregue); pedido sem palete não anda; e anda uma vez só — se o PCP puxar de volta pra "Pronto" na mão, fica em Pronto, o sistema não empurra de novo.
📋 Fica no histórico do pedido: "Pronto → Pronto p/ carregar (etiqueta impressa)".
✔️ Botão "já resolvi" no pedido de ajuste do cliente. Até agora um ajuste só fechava de um jeito: mandando uma versão nova da amostra ou da arte. Quando o assunto se resolvia por fora — no telefone, numa visita, ou a caixa mudou de rumo — o bilhete ficava pendurado pra sempre na tela do vendedor, sem botão nenhum pra tirar.
👀 O PCP passa a ver todos os ajustes. Antes só aparecia aqui o ajuste da arte. O do orçamento e o da amostra existiam, o cliente e o vendedor viam, e quem monta a caixa não. Agora aparecem os três, cada um com o seu botão.
📋 Não apaga nada: fechar registra no histórico quem fechou e quando, com o texto do que o cliente tinha pedido.
ℹ️ Desfazer aprovação continua sendo outra coisa — mexe na aprovação, não no pedido de ajuste. São dois registros separados.
🗑️ Dá pra excluir a arte. No Desenvolvimento, do lado do "ver a arte atual" agora tem 🗑️ excluir a arte. Mandou o PDF errado, tira ele de cima da caixa: se havia uma versão anterior, ela volta a ser a arte atual, e o próximo envio pega o número de volta (excluiu a v3, o próximo é v3 de novo).
🔒 Arte que o cliente já aprovou não se exclui — o botão nem aparece. Senão o "sim" que ele deu na v2 passaria a valer em cima da v1, e a caixa apareceria aprovada numa arte que ele nunca viu. Pra excluir mesmo, é só desfazer a aprovação antes.
📝 Fica registrado no histórico da caixa quem excluiu e qual versão.
📄 O orçamento do app do vendedor agora é igual ao do sistema. O PDF que ia pro cliente era uma versão mais pobre: sem as cores, sem o peso por caixa e no total, sem o programa de entregas e — o pior — sem a linha da ferramenta cobrada à parte, que entra no TOTAL. O documento não fechava a conta: subtotal + IPI não dava o total impresso.
🔢 O preço unitário saiu com 3 casas, como no sistema. Com 2 casas o cliente não conseguia refazer a conta: R$ 0,71 × 12.600 não bate com R$ 8.972,36 (o preço de verdade é R$ 0,712).
🚚 As entregas agora dizem a mesma coisa nas duas telas. Era "3 entregas · data a definir" no cartão e nada no PDF; agora é "3 entregas · 700 cx cada · data a definir" na tela, no PDF e no WhatsApp.
🧯 Orçamento antigo não quebra: os que foram enviados antes disso simplesmente não mostram as linhas novas — nada de "0,000 kg".
🛡️ A trava anti-apagão dos cadastros de gente agora existe de verdade. Ela tinha sido posta no cano errado: vendedores, motoristas, operadores, laudistas e expedidores entram por outro caminho e passavam direto por ela. Agora os dois caminhos (o sistema e os painéis) conferem o servidor antes de gravar.
🚫 O que ela barra: um aparelho com a lista desatualizada gravando por cima e levando junto quem ele nunca viu — 5 vira 4 e ninguém percebe. Excluir pela tela continua funcionando normal, e cadastrar gente nova também.
📴 Sem confirmação do servidor, não grava. Se a internet cair na hora de conferir, o salvamento espera — nada se perde, a lista já está guardada no aparelho.
🔎 Achado no caminho: o cadastro de vendedores tinha uma cópia velha e morta no servidor, que ninguém lê. A lista de verdade sempre esteve certa, com todo mundo e as senhas.
💰 Dar baixa no pedido gera a conta a receber sozinho. Com o vencimento saindo da condição de pagamento — "30/60/90 dias" vira três contas, cada uma na sua data. Sem condição, é à vista: vence hoje.
🔗 Fecha o ciclo do crédito. O limite disponível do cliente desconta as contas a receber em aberto — antes isso só valia se alguém lembrasse de lançar na mão, e limite que depende de alguém lembrar não protege ninguém.
🔒 Não duplica: dar baixa de novo no mesmo pedido não cria outra conta. Já uma baixa parcial nova gera as contas dela — é outro valor a receber.
🪙 A divisão em parcelas não perde centavo: a sobra do arredondamento vai na última.
🛟 Se a geração falhar, a baixa não é afetada — o pedido já foi faturado, e a conta se lança na mão.
v2.37.222 CONSERTO
07/08/2026
🖨️ Máquina produzindo aparecia LIVRE no Mural. Aconteceu com a Slotter. O erro era meu, na versão passada: eu tratava "faz 12 horas que ninguém mexe no app" como "não está rodando".
🔍 A causa: o app do operador só carimba a hora quando alguém mexe nele — não existe um sinal automático de minuto em minuto. Então um pedido longo passa meio dia sem "dar notícia" estando em plena produção, e eu tratava isso como apontamento largado.
✅ Agora LIVRE quer dizer uma coisa só: a máquina não tem NENHUM apontamento. Se o apontamento estiver velho, o cartão continua mostrando a produção e avisa embaixo: "o app do operador não dá notícia há 20h — confira se a máquina está mesmo neste pedido".
🛡️ E o botão 🔓 Destravar não toca mais no que a máquina está fazendo, por mais horas que faça sem ninguém mexer no app. Só entra o que ficou para trás — ou o que está largado há mais de 3 dias, que aí não é produção, é abandono.
🔔 O alerta de "app sem dar notícia" também subiu de 2h para 8h, senão tocava à toa em pedido longo.
💵 O adiantamento se desconta sozinho. Quando o orçamento vira pedido, o valor usado sai do saldo do cliente automaticamente — antes alguém tinha que lembrar de abaixar na mão. Aparece um aviso dizendo quanto foi usado e quanto sobrou em conta.
🔒 Não desconta duas vezes. A baixa fica carimbada no orçamento; se a conversão rodar de novo, ela é ignorada. E o saldo do cliente nunca fica negativo: se ele tinha menos que o combinado, usa só o que tinha.
🔎 Dá pra rastrear: o orçamento guarda quanto consumiu e quando — é por ele que se descobre qual pedido comeu o adiantamento.
🔓 Destravar tudo de uma vez. No Mural, quando houver apontamento preso, aparece o botão 🔓 Destravar N presos. Ele abre uma lista com máquina, pedido, operador, há quanto tempo está parado e quantas caixas já saíram — tudo marcado, e você desmarca o que não quiser.
✅ Nada é apagado. É o mesmo caminho do 🔓 do app do operador e do fim de turno: o que já foi produzido continua guardado e o próximo operador continua de onde parou. O que muda é só que o pedido deixa de ficar preso.
🛡️ Quem está produzindo agora nunca entra na lista — nem marcando tudo. Só aparece apontamento sem nenhuma atualização há mais de 12 horas.
👤 Fica registrado quem destravou. Só admin e PCP podem usar o botão.
🏦 Limite de crédito por cliente. No cadastro do cliente entraram Limite de crédito e Adiantamento em conta. No orçamento, um painel avisa quando o valor passa do limite.
💳 A divisão que você pediu: o que cabe no limite vai parcelado na condição de pagamento do cliente; o que passa sai à vista. Ninguém fica impedido de comprar — só muda a forma de pagar.
💵 Adiantamento abate antes. Dinheiro que já entrou não consome limite (seria cobrar duas vezes pelo mesmo risco), e a sobra fica em conta pro próximo pedido.
📉 O limite desconta o que ele já deve. Disponível = limite − contas a receber dele em aberto. Limite que ignora dívida não é limite: o cliente estoura sem o sistema piscar.
🧾 O documento do cliente passa a mostrar adiantamento, saldo a pagar e a divisão parcelado/à vista. A divisão fica gravada no orçamento — o papel vale o que foi combinado no dia, mesmo que o limite mude depois.
🔔 Alertas da fábrica — o sistema agora chama você. Botão 🔔 Alertas no topo, com o número do que está pedindo gente agora. Funciona em qualquer aba, não só no Mural. Vermelho pisca.
👀 Ele olha seis coisas: máquina parada há muito tempo · app do operador que parou de falar · ajuste demorando · máquina rodando abaixo da meta · máquina livre com o turno rodando · apontamento em máquina fora do cadastro.
📋 Cada alerta diz o que fazer — "ver se falta clichê, faca ou chapa", "conferir o celular da máquina". E os mais graves aparecem também na faixa do Mural, pra quem está olhando a TV na fábrica.
🍽️ Refeição não toca o sino. Sino que toca todo dia meio-dia vira sino que ninguém escuta.
⚙️ Os limites são seus: no ⚙ dentro do painel dá pra mudar quantos minutos de parada viram alerta, a partir de que % da meta é "devagar", e assim por diante. Vale só neste aparelho — mudar aqui não mexe no de ninguém.
🖥️ E o Mural foi consertado: agora é um cartão por máquina, sempre. Ele estava desenhando um cartão por apontamento aberto — na fábrica isso virou 19 cartões da mesma Slotter, com apontamentos de 44 dias atrás aparecendo como se fossem de agora, e um "ritmo de 3 cx/h" que não era ritmo de nada.
🔓 Apontamento parado há mais de 12 horas é trava presa, não produção: sai do cartão, vira um aviso amarelo no rodapé ("6 apontamento(s) preso(s) — destravar no app") e entra na lista de alertas. Enquanto ninguém destrava, aquele pedido fica preso pro próximo operador.
v2.37.217 PROTEÇÃO
07/08/2026
🧨 O motor de custos estava por um fio. Ele conferia os pedidos com window.STATE — que não existe: a lista de pedidos é declarada de um jeito que não vai parar ali. Funcionava só porque a tela de Etiquetas cria um window.STATE vazio de raspão, e isso bastava pra checagem passar.
⚠️ O risco: se aquela linha do Etiquetas saísse, o Painel de Custos, o Ponto de Equilíbrio e o Resultado por Cliente passariam a ver zero pedido — sem erro, sem aviso, só números errados.
✅ Trocado pela checagem certa nos 3 lugares (custos e o rodapé de versão). Nada muda na tela; o que muda é que agora não depende de acidente.
⚙️ OEE — a nota da fábrica num número só. Tela nova em Análises ▸ ⚙️ OEE. Responde: de cada hora de turno que você paga, quanto virou caixa boa? É o índice que a indústria usa pra comparar fábrica com fábrica. Acima de 85% é classe mundial; 60% é a média.
⏳ A tela mostra ONDE o tempo foi, degrau por degrau: turno planejado → máquina operando (o que saiu em parada, ajuste e turno sem apontamento) → no ritmo cadastrado (o que se perdeu rodando devagar) → virou caixa boa (o que a perda comeu). O último degrau dividido pelo primeiro é o OEE — dá pra ler sem entender de fórmula.
🔴 Por que a máquina parou, do maior pro menor, em horas. É a lista do que atacar primeiro. Refeição e troca de turno ficam de fora, porque o almoço já está descontado do turno.
🏭 Máquina por máquina, com os três fatores separados — assim dá pra ver se o problema daquela máquina é parada, ritmo ou perda.
🎯 Nada é chutado. O turno é o cadastrado pra cada máquina, a velocidade é a mesma que o cronograma usa e a perda vem da mesma fonte da tela de Perdas. Apontamento sem velocidade cadastrada fica de fora da conta de Desempenho — e o sistema avisa quantos foram.
⚠️ Passar de 100% não é recorde, é cadastro desatualizado — aparece com ⚠ e amarelo, nunca verde. Máquina que rodou além do turno e velocidade cadastrada abaixo da real são apontadas com nome e sobrenome.
🏆 Resultado por Cliente (Financeiro → 🏆 Resultado por Cliente). O Faturamento ABC diz quem compra mais — e isso não é a mesma pergunta que quem dá dinheiro. Cliente grande com preço apertado pode render menos que um pequeno bem precificado.
📊 Por cliente, no mês: quanto faturou, o R$/kg praticado, o custo variável, a margem de contribuição, o fixo rateado e o resultado — com quem está no vermelho destacado.
⚖️ O fixo é rateado por peso (kg do cliente ÷ kg do mês). É divisão, não medição: serve pra comparar clientes entre si, não pra dizer que um custou exatamente aquilo. A tela avisa isso.
🧮 Usa o mesmo motor do Painel de Custos: a soma dos resultados bate com o lucro do mês, e o rateio soma exatamente o custo fixo. Se recalculasse por fora, as telas divergiriam.
v2.37.214 PROTEÇÃO
07/08/2026
🛡️ Trava contra sumiço de gente do cadastro. A trava que já existia só barrava lista vazia — não pegou o que aconteceu com o Armando, que sumiu do cadastro de vendedores quando a lista foi de 2 pra 1 e ficou assim dois meses, com os orçamentos dele apontando pra um id que não existia mais.
🧩 O estrago não é apagão, é encolhimento: um aparelho com a lista desatualizada grava por cima e leva junto quem ele nunca viu. Agora gravar uma lista menor que a do servidor é bloqueado, com recado pra recarregar a página.
✂️ Excluir de propósito continua funcionando — o botão de excluir avisa a trava antes de salvar, e só aquela gravação passa.
👥 Vale pros cadastros de gente: vendedores, motoristas, operadores, laudistas, manutentores, encarregados, compradores e conferentes. Pedido e carga ficam de fora — ali encolher é normal.
v2.37.213 CONSERTO
07/08/2026
🏷️ O selo ATUAL desta lista estava grudado na v2.37.202 — dez versões atrás. Era escrito na mão e ninguém lembrava de mudar de lugar a cada versão nova.
✅ Agora ele se coloca sozinho na entrada mais nova, sempre. Não tem mais como envelhecer, não importa quem suba a próxima versão.
📺 Mural da Fábrica — a TV do chão de fábrica. Aba nova em Produção ▸ 📺 Mural: um cartão por máquina, se pintando sozinho. Verde = rodando no ritmo, amarelo = devagar (abaixo de 85% da meta) ou em ajuste, vermelho = parada, cinza = livre.
🔴 A máquina parada diz por quê e há quanto tempo — "⚙️ Quebra de máquina · há 45 min". Passou de 30 minutos, o cartão começa a piscar com ⚠. Parada vem sempre no topo da tela, que é o que precisa de gente.
🍽️ Refeição e troca de turno ficam azuis, não vermelhas. Pintar a fábrica de vermelho todo dia na hora do almoço acostuma o olho e o vermelho perde a força.
⏱️ Ritmo de verdade: caixas por hora descontando as paradas, com a meta do pedido do lado. Mais a barra de quanto já saiu do pedido e o total de caixas do dia.
👁️ Máquina fora do cadastro NUNCA some. Se o operador apontar num apelido que não bate com nenhuma máquina cadastrada, o mural mostra assim mesmo com o selo FORA DO CADASTRO — foi um apelido torto que já escondeu 20.000 chapas prontas.
📺 Botão "Modo TV" deixa em tela cheia com letra grande, pra pendurar um monitor na fábrica. Se pinta sozinho a cada 15 segundos.
v2.37.211 CONSERTO
07/08/2026
🤝 Orçamento feito no PCP agora aparece no app do vendedor. O app só listava solicitações — o que o próprio vendedor mandou. Orçamento montado direto na central, mesmo com o vendedor escolhido, não virava solicitação e por isso nunca chegava nele. A tela ficava vazia mesmo com os orçamentos existindo no nome dele.
🧪 E sem a linha, o desenvolvimento também sumia — o bloco de etapas se pendura no orçamento. Agora aparece: etapa de cada caixa, há quantos dias está parado e o que o cliente pediu.
🔒 Orçamento montado pelo PCP entra só pra leitura (diz "montado pelo PCP") — editar e excluir continuam sendo só do que o vendedor criou.
🚫 Não duplica: se o mesmo número já veio como solicitação dele, é a solicitação que aparece — é ela que tem as caixas pedidas, a foto do modelo e o que ele escreveu.
🔁 Conta que se repete todo mês. Aluguel, pró-labore, internet: marque "Repete todo mês" ao lançar e os próximos 12 meses entram sozinhos, cada um com seu vencimento. Dá pra pôr uma data limite.
📆 Cada mês é uma conta de verdade, não um cálculo. Por isso dá pra pagar agosto e deixar setembro em aberto, mudar o valor de um mês só, e a previsão de caixa enxerga tudo.
🗑️ Dois botões na linha: 🗑️ apaga só aquele mês; 🗑️🔁 apaga esta e as futuras e encerra a repetição. As já pagas ficam no histórico.
📅 Dia 31 em fevereiro vira o último dia do mês, não 3 de março. E gerar de novo não duplica: cada mês só existe uma vez.
📦 A caixa agora dobra do lado certo. No desenho do palete, a maleta dobra ao meio no sentido do vulto (o lado que a impressora mede). Antes o sistema dobrava sempre o campo Chapa C — e quando a chapa estava cadastrada ao contrário ele partia o lado errado.
🔍 Foi o que aconteceu com a CX 09 do KIMETAIS (915×310×435, chapa 757×2497): saía "caixa dobrada 361×2497", uma caixa de 2,5 metros deitada no palete, e o palete precisou virar 1000×2500 pra caber. Agora sai 1231×757, que é a caixa dobrada de verdade.
⚠️ Ele avisa quando a chapa está ao contrário — aparece um recado embaixo de "Caixa dobrada" dizendo que o vulto está no campo Chapa L. O palete sai certo mesmo assim, mas vale arrumar o cadastro.
✅ Conferido nas 145 caixas cadastradas: 118 não mudaram nada. Só duas estavam erradas (CX 09 do KIMETAIS e a 51897 do FK Grupo) — as duas com a chapa trocada de campo.
🔮 Previsão de caixa — 8 semanas. Na tela de Contas (agora 📅 Contas & Previsão): você informa o saldo em caixa hoje e o sistema vai somando o que entra e tirando o que sai, semana a semana.
🚨 Ele avisa em que semana o caixa fica negativo — em vermelho, dizendo quantas semanas faltam. Se não ficar, diz qual é o menor saldo previsto. O que interessa não é o total do mês; é o dia em que falta dinheiro.
⏰ Conta atrasada entra na 1ª semana, não no passado. Ela não sumiu — está em aberto agora, e jogá-la pra trás esconderia justamente o problema.
💡 Só conta o que está em aberto: o que já foi baixado não entra na previsão.
📅 Contas a pagar e a receber (Financeiro → 📅 Contas a Pagar/Receber). O Financeiro sabia o que já aconteceu; agora sabe o que vai vencer. Boleto de sexta e cliente que paga dia 10 deixaram de morar num papel.
🚦 No topo: quantas venceram, quantas vencem hoje, quantas vencem em 7 dias e o saldo em aberto (a receber menos a pagar). Na lista, vencido sai em vermelho e "vence hoje" em amarelo.
✓ Dar baixa marca a data e quem baixou — e dá pra desfazer. Filtros por tipo (pagar/receber), situação e busca por descrição ou fornecedor.
⚠️ Dar baixa aqui NÃO lança custo no Centro de Custo. Se lançasse, o mesmo gasto entraria duas vezes no custo do mês — o Painel já soma os lançamentos. Aqui é o controle do vencimento.
💵 Tela nova: Entra & Sai (Financeiro → 💵 Entra & Sai). O Financeiro tinha as duas metades separadas e elas nunca se olhavam: o Painel de Custos só mostrava o que a fábrica gasta, o Faturamento ABC só quem mais compra. Faltava a conta simples.
📅 Últimos 12 meses: quanto entrou (notas faturadas), quanto saiu (lançamentos do mês + fixos) e o que sobrou, com barra comparando. Toque no mês pra ver o detalhe.
💸 Pra onde foi o dinheiro no mês escolhido, por categoria. Clichê e faca ficam de fora — quem paga é o cliente, mesmo critério do Painel de Custos.
📦 Caixas: saiu do estoque × foi faturado. Entrou no PA, saiu do PA e quanto foi baixado como faturado. O que saiu e não faturou aparece em vermelho — é dinheiro que ainda não virou nota.
🔎 "Palete que ficou pra trás" ganhou busca e virou lista agrupada. Com 12 paletes num lote só, a tela virava uma rolagem sem fim. Agora cada lote é uma linha — caixa, cliente, pedido, quantos paletes e quantas caixas — e abre ao tocar pra devolver o palete.
🔍 A busca filtra por cliente, caixa ou número do pedido.
↩ Palete que ficou pra trás volta pro estoque. A carga saiu, foi entregue, mas um palete não foi no caminhão — agora dá pra devolver ele. Botão "↩ Palete que ficou pra trás" no Estoque PA, ao lado de "Saída de Caixas".
🧩 Onde faltava: o ↩ de voltar palete já existia, mas só dentro do lote — e o lote some da tabela do PA quando o último palete sai. Ou seja, justo no caso em que mais se precisa não havia por onde entrar. A tela nova lê o histórico de saídas, não o estoque, então enxerga lote que já sumiu.
📦 Devolvendo o palete, a caixa volta a aparecer no Estoque PA com a quantidade certa, e entra um movimento de entrada explicando o motivo.
⚠️ O pedido continua como está (carregado/entregue) — quem ajusta isso é você na carteira, porque a carga realmente saiu.
🗑️ Lixeira de pedidos. Excluir pedido deixou de ser definitivo. Agora ele vai pra lixeira e volta com ↩️ Restaurar — inteiro, com produção, paletes e histórico. O botão fica em PCP → 🗑️ Lixeira, no canto das abas.
⏳ Guarda 60 dias, mostrando quem excluiu e quando. Depois disso some sozinho — lixeira não é arquivo morto.
🧩 Por que faltava: o servidor guardava só o id do pedido excluído (pra ele não voltar pela sincronização), nunca o conteúdo. Recuperar exigia backup do banco — foi assim que os pedidos 23434, 23574 e 23694 voltaram em 03/08.
⚠️ Restaurar tem ordem: a lápide sai do servidor antes do pedido voltar. Ao contrário, a sincronização vê o id barrado e descarta em silêncio — o pedido sumiria de novo sem dar erro nenhum.
🔩 O Almoxarifado de Peças ganhou campo de Fornecedor. Antes não tinha nenhum: dava pra ver saldo e prateleira, mas não de quem se compra aquilo.
🏪 Nas peças que JÁ existem, cada item da lista ganhou um botão 🏪 — toca, escolhe (ou digita) o fornecedor e salva. Não precisa recadastrar nada.
🆕 No cadastro de peça nova (no modal "Cadastrar peça" e no formulário rápido da entrada por bipe) o campo já vem junto, sugerindo quem vende aquela categoria: Mecânica/Elétrica/Fixação puxa quem vende peças, Ferramental puxa ferramentas, EPI puxa EPI, e por aí.
🔎 O fornecedor aparece na linha do item (🏪) e a busca acha por ele — dá pra digitar o nome do fornecedor e ver tudo que se compra dele. No sistema, em Cadastros → Peças, virou coluna na tabela e campo no formulário.
Sem banco novo: o fornecedor entra junto com os dados da peça. Não precisa do Luan.
📄 O orçamento que o cliente baixa passou a sair COM as quantidades, mesmo nas propostas antigas. Antes ele dependia de uma cópia gravada na hora de puxar do orçamento — proposta feita antes disso saía sem quantidade nenhuma. Agora o servidor busca o orçamento de origem e monta o documento a partir dele.
✅ O botão do cliente diz o que ele está aprovando. Era só "Aprovar" — agora é "Aprovar orçamento", do lado do valor por caixa. Com várias caixas, o de cima virou "Aprovar o orçamento das N caixas".
🏷️ Só a logo no cabeçalho. Saiu o nome escrito ao lado dela (repetia o que a própria logo já diz). Ficou a logo, com Caixas de Papelão Corrugado e Boracéia/SP abaixo. Sem logo cadastrada, o nome volta no lugar dela pra não ficar cabeçalho vazio.
🧾 Romaneio: "Carregado por" agora é o empilhadeirista de verdade. O papel saía com o nome de quem estava logado no PC (o escritório), e não de quem carregou o caminhão. O app da Expedição sempre guardou o conferente que bipou os paletes, mas o romaneio procurava esse nome no lugar errado e nunca achava. Agora sai o login do app — e o "Conferido por" vem preenchido com o mesmo nome, porque é a mesma pessoa. O "Encarregado" continua em branco pra assinar à mão.
Vale nos dois romaneios (o da carga bipada e o do plano de carga) e fica guardado no histórico, então a reimpressão sai igual. Se não houver conferente registrado, o campo sai em branco pra assinar — antes ele chutava o nome de quem estava no PC. Romaneio já impresso guarda o nome antigo: pra corrigir, precisa gerar de novo.
📦 A tela de Expedidores voltou a mostrar os nomes. A lista dos conferentes chega do servidor depois que você entra no sistema — e a tela não se repintava sozinha, então ficava sempre em branco, como se ninguém estivesse cadastrado. Agora, assim que a lista chega, a tabela aparece; e se você abrir a tela e ela estiver vazia, o sistema busca na hora.
✏️ Voltou o botão de editar. Com os nomes de volta na tabela, cada conferente tem ✏️ Editar (puxa nome e senha pro formulário de cima) e ✕ pra excluir. A coluna ganhou o título "Ações".
🔗 O link do app de Expedição estava morto. Apontava pro endereço antigo do sistema (github.io/jp-painel), que não existe mais. Agora ele é montado a partir de onde o sistema está rodando — nunca mais fica velho ao mudar de servidor.
v2.37.199 CONSERTO
06/08/2026
🔢 Puxar do orçamento não herdava o número. Era a raiz do descasamento: a tela mandava o id do orçamento mas nunca o número, e o servidor então tirava um número novo. Puxar do nº 9 criava a proposta ORC-0010. Agora nasce ORC-0009.
🏷️ A etiqueta da amostra não espera mais o cliente. O botão ficava escondido até o orçamento ser aprovado — mas quem faz a amostra é a fábrica, e muita vez ela sai junto com o orçamento. Agora o botão está sempre lá, só avisando quando ainda não houve aprovação.
↩️ Dá pra desfazer uma aprovação. O "sim" do cliente não tinha volta. Agora tem ↩️ desfazer ao lado de cada aprovação — só pela JP, nunca pelo portal. Caixa que já virou pedido não aceita: a produção andou em cima daquela aprovação. O histórico guarda quem aprovou e quem desfez.
🔗 Link do cliente pela metade do tamanho: de 149 pra 90 letras. O código passou de 64 pra 16 caracteres — continua seguro (64 bits, e o portal trava depois de 40 chutes) e agora cabe numa linha de WhatsApp. Links antigos continuam valendo.
📄 O orçamento que o cliente baixa ficou igual ao do sistema. Puxando a proposta do orçamento, o documento sai com a mesma quantidade, o mesmo unitário e o mesmo total — mais o nome da empresa, o estilo da caixa, o peso por caixa e o total, a validade até a data, o IPI isento por carta e as condições.
🔗 Isso só vale pra proposta puxada do orçamento. Registrada solta como amostra, ela não tem orçamento nenhum pra copiar — sai só com o valor por caixa.
📄 O cliente pode baixar o orçamento. No portal apareceu o botão "Baixar orçamento": abre o documento numa folha branca, com quantidade, unitário, totais, impostos e condição de pagamento — e o botão Baixar / Imprimir pra salvar em PDF.
📦 Como o documento chega lá: o portal não tem acesso ao sistema, então uma cópia comercial do orçamento viaja junto com a proposta quando ela é puxada de um orçamento. Se a proposta nasceu de uma amostra (sem orçamento), o documento é montado com o que ela mesma tem.
🔒 Só vai o que o cliente pode ver — nada de R$/kg, custo ou margem.
🏷️ Logo maior no orçamento. Ela era um selo pequeno ao lado de um título grande e sumia no papel. Agora tem a altura do nome da empresa, com Caixas de Papelão Corrugado e Boracéia/SP logo abaixo dela.
🔗 O link do cliente agora diz de quem é. Ele carrega o nome do cliente e o número da proposta antes do código — dá pra saber do que se trata sem abrir:
…/portal.html?cliente=ECOLUBRI-LUBRIFICANTES&proposta=ORC-0008&t=afd2b26d…
🔒 Não mexe na segurança. Quem manda no acesso continua sendo o código do fim — trocar o nome na barra de endereço não abre a proposta de outro cliente.
📲 A mensagem do WhatsApp também passou a dizer o nome do cliente junto com o número da proposta.
✅ Links antigos continuam funcionando.
🔓 Dá pra apagar proposta de teste que o cliente já viu. O aviso continua aparecendo primeiro — ele é importante. Mas agora tem saída: se for teste, você confirma digitando o número da proposta e ela vai embora.
📋 Fica registrado quem forçou e quais caixas tinham aprovação do cliente — o histórico guarda a linha inteira.
🚫 A outra trava não tem saída: caixa que já virou pedido não apaga nem forçando. Ali o pedido ficaria órfão na produção, e isso é problema de fábrica.
📱 Vale no painel central e no app do celular.
v2.37.194 CONSERTO
05/08/2026
🏷️ A etiqueta da amostra saía em branco. Ela dependia de uma regra que escondia a página inteira na hora de imprimir e mostrava só o quadro da etiqueta — qualquer outra coisa aberta atrás derrubava isso e o papel saía vazio.
🖨️ Agora usa o mesmo caminho da etiqueta de clichê: monta um documento próprio, com o seu papel 75×100mm — o mesmo tamanho em que a impressora já está regulada. Nada do sistema interfere.
📱 Vale no painel e no app. No celular, se o navegador bloquear a janela nova, ele imprime por um quadro escondido em vez de simplesmente não fazer nada.
🔳 O QR vira imagem embutida no documento — desenho de tela não atravessa pra outra janela, e era mais um jeito da etiqueta sair sem o código.
🤝 Vendedor escolhido no cadastro, na hora de registrar a amostra. No app do Desenvolvimento e no painel central, o campo deixou de ser e-mail digitado e virou lista do cadastro de vendedores — nos três lugares: registro novo, puxar do orçamento e o app.
📧 O e-mail vem junto, do próprio cadastro. Ninguém digita, ninguém erra, e o aviso chega em quem tem que chegar.
🔗 É o que faz a solicitação ter dono. O app do vendedor filtra por vendedorId: sem ele, o orçamento nascido de uma amostra não aparecia pra ninguém. Agora o vendedor viaja da amostra até a fila de Solicitações.
📝 O vendedor fica gravado na proposta também (id e nome), e o detalhe passa a mostrar o nome em vez do e-mail. Campo continua opcional — amostra sem vendedor grava igual.
🤝 O vendedor passou a ver mais que o status. No bloco de desenvolvimento de cada orçamento agora aparece:
⏳ Há quanto tempo cada caixa está parada — amarelo a partir de 3 dias, vermelho com "vale ligar" a partir de 7. Conta do último movimento de verdade (o histórico), não de uma edição qualquer.
✏️ O que o cliente pediu de ajuste, com o texto dele e quem pediu — antes só dizia "Cliente pediu ajuste" e o vendedor não sabia o quê.
✅ Quem aprovou o quê e quando, com nome e cargo — pro vendedor saber com quem falar do lado do cliente.
🔕 Caixa liberada ou que já virou pedido não mostra contador: ela não está esperando ninguém.
📱 App do Desenvolvimento em dia com o painel central. Cartão da proposta com a etapa e quantas caixas faltam preço; cada caixa com cor e número (#1, #2); "⏳ na fila de Solicitações" no lugar do lançar preço na mão; e botão de excluir no fim da tela.
🏷️ O selo de versão do app estava travado na v2.37.185. Ele rodava código novo mostrando número velho — o script de bump não cobria esse marcador (JP_VERSAO_PAINEL, que só existe nesse app). Corrigi o selo e o script, pra não voltar a acontecer.
🚚 Botão "Programar entregas" no item do orçamento. Abre um painel com a quantidade de cada entrega editável — dividir igual é só o ponto de partida. Na prática o cliente pede 4.000 na primeira e o resto depois, e agora dá pra escrever isso.
✅ A soma tem que fechar. O painel mostra ao vivo "10.000 de 10.000 ✅ fecha" (ou quanto falta/passou) e não deixa salvar o item com a conta errada — programação que não fecha vira documento errado na mão do cliente.
🏭 O PCP acompanha. Ao virar pedido, sai um pedido por entrega com a quantidade certa e o selo 🚚 ENTREGA 2/3 no card, mostrando o total combinado. As datas saem escalonadas e o PCP ajusta se o cliente mudar.
⚠️ Não confundir com o "programa de entregas" da aba interna: aquele é contrato recorrente (cada ciclo leva a quantidade cheia) e serve pra diluir clichê e faca no custo. Este divide uma quantidade e é combinado comercial. Se os dois estiverem ligados, eles se compõem — N ciclos × M parcelas.
🗑️ Excluir proposta no Desenvolvimento agora avisa direito quando a API ainda não foi reiniciada, em vez de "Rota não encontrada".
🗑️ Excluir proposta no Desenvolvimento. Botão dentro da proposta aberta, com aviso dizendo o que vai embora (número, cliente, quantas caixas).
🛡️ Duas travas no servidor, não só na tela: recusa se alguma caixa já virou pedido (o pedido ficaria órfão na produção) ou se já passou do orçamento — nesse ponto o cliente já viu e aprovou, e apagar levaria a prova junto.
📋 O histórico fica. Quem aprovou o quê continua registrado depois da exclusão, com uma linha final marcando o que foi apagado e por quem.
🧹 Sai também da fila de Solicitações, pra não sobrar pedido de orçamento apontando pra proposta que não existe mais.
🚚 Entrega programada por item no orçamento. Campo Entregas ao lado da quantidade: 10.000 caixas em 3 vezes vira "3 entregas · 3.334 + 2× 3.333 cx · data a definir". A fábrica produz tudo de uma vez e entrega parcelado.
📄 Aparece no documento do cliente (tarja amarela no item), no texto do WhatsApp, na lista de itens e no app do vendedor.
🗓️ A data fica a definir de propósito — quem marca é o cliente. O que o orçamento fecha é a quantidade de cada entrega.
🔢 A divisão não perde caixa: 10.000 em 3 não é 3.333 três vezes (daria 9.999) — a sobra entra nas primeiras entregas.
ℹ️ Isso não mexe em preço nem peso. É outra coisa do "programa de entregas" da aba interna, que serve pra diluir clichê e faca no custo.
📋 Lista do Desenvolvimento igual à de Orçamentos. Cada proposta virou um cartão de verdade — número, cliente, etapa, caixas e botão de abrir. Antes era linha solta: duas propostas coladas viravam um bloco só de texto.
🎨 Preço por caixa, não somado. O cartão mostra a faixa (ex.: R$ 2,997 a R$ 4,03 por caixa). Somar os unitários dava um "R$" que não é dinheiro nenhum — o valor do negócio depende da quantidade, que a amostra ainda não tem.
🖼️ Arte não sobrescreve mais a de outro cliente. Duas artes chamadas "arte.pdf" gravavam no mesmo lugar no servidor e a tela de aprovação passava a mostrar a arte errada. Agora quem nomeia o arquivo é o servidor — mesma correção que já tinha sido feita nas fotos. Vale também pro PDF do pedido.
🧪 Amostra registrada vai pra fila de Solicitações. Quem registra uma amostra no Desenvolvimento não precisa mais digitar preço na mão: ela entra na mesma fila onde caem as solicitações do vendedor, o PCP orça com a ferramenta de verdade e o preço volta sozinho pra caixa — unitário, clichê e faca. O funil destrava sem ninguém redigitar nada.
🤝 O vendedor vê no app. O vendedor escolhido no orçamento vira o dono da solicitação, então o orçamento aparece no app dele com a etapa de cada caixa. Amostra e orçamento carregam o mesmo número.
🎨 Caixa com cor própria. Na proposta, cada caixa ganhou cor e número (#1, #2, #3). Antes todas herdavam a cor da etapa e ficavam idênticas — com foto, amostra e arte empilhadas, não dava pra saber onde uma terminava e a outra começava.
✏️ O lançar na mão continua ali, agora como atalho pra furar a fila.
v2.37.185 CONSERTO
05/08/2026
🚨 Orçamento do vendedor não chegava em Solicitações. O documento na nuvem estava aninhado em dobro: o app lia um objeto onde esperava uma lista, o envio estourava e o erro era engolido — a solicitação ficava só no aparelho e ninguém via. Agora os dois lados desaninham na leitura, e a próxima gravação já deixa o documento certo.
📱 Nada se perdeu: o app guarda no aparelho o que não conseguiu enviar. Abrindo o app do vendedor no mesmo celular, as solicitações sobem sozinhas.
📷 Fotos repetidas no desenvolvimento. Três fotos diferentes viravam a mesma: o iPhone chama toda foto de "image.jpg" e o servidor gravava por cima. Agora quem nomeia o arquivo é o servidor — e isso também impedia uma foto de apagar a de outra caixa.
🤝 App do vendedor mostra o desenvolvimento. Nos orçamentos dele aparece quais já viraram desenvolvimento e a etapa de cada caixa.
🔢 Um número só, e quem chega primeiro registra. Solicitação do vendedor, orçamento e proposta de desenvolvimento são o mesmo negócio — agora carregam o mesmo número, tirado de um contador único no servidor. A solicitação passou a nascer numerada (antes não tinha número nenhum) e as outras portas herdam. Dois consertos por trás disso: pedir número de orçamento devolvia o número do clichê, e o contador era semeado sem enxergar as solicitações — por isso a proposta nova saiu como ORC-0001 em vez de continuar a fila.
🤝 Vendedor viaja com a solicitação. O orçamento feito a partir dela já nasce no nome de quem trouxe o negócio, e o cliente novo entra no cadastro com esse vendedor em vez de ficar órfão.
🔍 A arte não borra mais ao aproximar. O PDF é vetor, mas era desenhado uma vez e depois esticado — dava a mesma coisa que ampliar foto. Agora, assim que o dedo para, a página é redesenhada na resolução do zoom: o texto miúdo e a linha de faca ficam nítidos de verdade.
✍️ A marcação virou traço, não imagem. Ela é redesenhada nítida em qualquer zoom, continua no lugar exato quando você afasta, e o desfazer ficou preciso — tira só o último traço.
O peso do desenho sobe só quando precisa, com teto pra não travar aparelho antigo.
📷 Dá pra anexar as fotos a qualquer momento, não só no registro. Proposta puxada do Orçamento nascia sem foto nenhuma e não tinha onde pôr — e é justamente nela que a amostra física chega depois.
📁 As fotos da amostra e dos testes feitos nela ficam no detalhe da caixa, com a contagem à vista e o aviso de que é registro interno. O cliente nunca vê nenhuma delas.
🔢 Um número só pro orçamento e pra proposta. O mesmo negócio aparecia como "nº 3" no Orçamento e "ORC-0008" no Desenvolvimento. Agora quem puxa do orçamento nº 0003 vira ORC-0003, e os dois módulos tiram número do mesmo contador — que se acerta sozinho a partir do maior número já usado.
👁️ A lista diz a etapa exata. Em vez de "Com o cliente", agora aparece o que está faltando: aguardando aprovação do orçamento → da amostra → da arte.
🤏 A arte se move como foto: dois dedos dão zoom, um dedo arrasta. E entrou uma seta de desfazer que apaga só o último traço — antes o único jeito era limpar tudo.
🎨 A cor da arte agora encontra a tinta certa. A ficha de tinta sai da análise do PDF e vem só com o tom (sem nome). O sistema agora passa pelo cadastro de Cores — que você já ligou uma por uma — em vez de chutar entre as 53 tintas do almoxarifado.
🔍 Consertado um erro feio de comparação de cor: o preto da arte (#1d1a1b) estava casando com BORDO, porque a conta antiga somava as diferenças de R, G e B e os dois são escuros. Agora cor lavada (preto/cinza/branco) só casa com cor lavada, e cor viva casa por matiz. Testado com o cadastro real: as 14 cores se reconhecem sem nenhum erro.
🔗 Bloco novo "Ligar a cor da ficha com a cor do cadastro" (Almoxarifado · Cartonagem): confirme uma vez qual cor é qual e o vínculo fica gravado na caixa — aí custo e ficha × real deixam de ser palpite. A sugestão já vem escolhida; o bloco some quando não sobra pendência.
📱 O vínculo confirmado também carimba o nome da tinta na ficha, então o app do operador mostra a comparação certa na máquina sem precisar do cadastro de Cores.
Camada técnica (corte, vinco, sombra) não aceita vínculo de tinta — a ficha de uma caixa real tinha 11 dessas no meio de 2 cores de verdade.
🟠 O botão 🖨️ Etiquetas fica LARANJA e o número VERMELHO quando tem etiqueta pra imprimir — dá pra ver do outro lado da sala. Sem pendência, ele volta ao normal e o número some.
🐛 Conserto: o número estava travado no total velho. Quem pintava o número era a tela principal, que só repinta quando o painel inteiro redesenha. Como as marcas de "já impresso" chegam do servidor depois disso, o botão continuava mostrando 137 em verde enquanto o aviso já listava certinho os 3 lotes que faltavam. Agora quem pinta é o próprio módulo do aviso, a cada 20 segundos.
Quem já estava com a v2.37.179 aberta: dá um Ctrl+Shift+R pra pegar o conserto.
🖨️ Clicar no botão Etiquetas abre o aviso do que falta imprimir. O número em cima do botão já é só o que falta (v2.37.176) — agora clicar nele abre direto o aviso "produto pronto, falta etiqueta", com cliente, lote, paletes e o botão de imprimir do lado, em vez da lista de reimpressão.
Sem nada pendente, o botão continua abrindo a lista de reimpressão de sempre. Se o aviso tinha sido adiado no "Agora não", clicar no botão traz ele de volta na hora.
🧻 Mais unidades no cadastro do insumo: saco e galão. Depois do balde (v2.37.175), o app do Almoxarifado agora também tem saco (cola em pó, amido) e galão na listinha de Unidade. Lista completa: un, kg, g, L, mL, m, cx, balde, saco, galão, pç, par, rolo.
Lembrete de sempre: só troque a unidade quando o produto não tem conversão. Se é a mesma tinta em embalagem diferente, deixe em kg e use o campo "Embalagem" (1 balde = 20 kg) — assim o Centro de Custo continua fazendo a conta sozinho.
🎯 A ficha de tinta agora fica do lado do consumo real — dá pra ver o desperdício.
📱 No app do operador, quando ele abre "Peguei tinta", aparece a ficha da caixa daquele pedido: AZUL DH 06 — ficha 14,2 kg · pegou 20, com ⚠️ quando passa de 10% acima. Ele vê na máquina, na hora, sem esperar ninguém avisar.
🎯 No painel central (Almoxarifado · Cartonagem) nasceu o quadro FICHA × REAL: pedido por pedido e cor por cor, quanto a ficha mandava gastar pelo que já foi produzido, quanto saiu de verdade e a diferença em kg e em % — o que mais estourou vem primeiro, e no rodapé o total do período.
🧵 O que o operador pegou e não está na ficha (outra cor, cola) aparece marcado como "fora da ficha", em vez de sumir da conta.
A ficha é estimativa por área impressa × gramatura: diferença grande pode ser desperdício ou ficha mal cadastrada — as duas coisas valem a pena descobrir. Só entra pedido com saída informada e caixa com ficha; e a cor precisa estar ligada à tinta (bloco "ligar a cor com a tinta comprada").
🏷️ Aviso no meio da tela quando tem produto pronto sem etiqueta. Palete sem etiqueta não pode ir pro carregamento — então agora, assim que chega um lote pronto que ninguém imprimiu, sobe um aviso grande no meio da tela com o botão 🖨️ Imprimir etiquetas do lado, cliente, lote, quantos paletes e quantas caixas.
🔢 O número do botão 🖨️ Etiquetas parou de mentir. Ele contava todo pedido que já teve palete algum dia (tinha chegado a 137) e nunca zerava — ninguém olhava mais. Agora ele conta só o que falta imprimir, fica vermelho e some quando você imprime.
🖨️ Quem imprime na máquina não é cobrado duas vezes: quando o operador imprime a etiqueta no app dele, o painel central fica sabendo na hora e o aviso some sozinho (funciona até se o aparelho estiver sem internet — sobe quando conectar).
✔️ Sobrou algum caso solto? O botão "Já imprimi" tira o lote do aviso. O "Agora não" adia por 10 minutos — o aviso volta sozinho, porque esquecer é justamente o problema.
Só entram lotes novos (dos últimos 7 dias, a partir desta versão) — o histórico velho não vira alarme. A marca de "impresso" é compartilhada entre os PCs e os aparelhos.
🧻 Unidade "balde" no cadastro do insumo. No app do Almoxarifado, quem controla a tinta por balde (e não por kg) agora acha balde na listinha de Unidade — junto de un, kg, g, L, mL, m, cx, pç, par e rolo.
Lembrete: se a unidade for balde, o saldo e o preço passam a ser por balde. Quem quiser continuar contando em kg deixa a unidade em kg e usa o campo "Embalagem" (1 balde = 20 kg).
🐛 Conserto: cliente antigo quebrava o cadastro da amostra. Dava o erro "invalid input syntax for type uuid" ao registrar com um cliente ou uma chapa de cadastro antigo — o sistema tem dois formatos de código e o módulo só entendia o novo. Agora o servidor entende os dois.
📱 O app do Desenvolvimento entrou na lista de apps (Cadastros → Administração), com QR pra instalar no celular igual aos outros. Antes só dava pra chegar nele digitando o endereço.
🎨 O operador dá a saída da tinta na máquina. Botão novo "Peguei tinta / insumo" no app do operador (durante a produção): ele procura pelo nome, diz se pegou 1 balde ou X kg, e o estoque baixa na hora — 32,5 → 12,5 kg. Fica gravado quem pegou, em qual máquina e pra qual pedido.
📒 Livro de movimentos na tela Almoxarifado · Cartonagem (Cadastros): entrou, saiu, quem, quanto, pra qual pedido e o saldo que ficou, com filtro de só saídas ou só entradas. Junta tudo num lugar só: a baixa do operador, o + / − do almoxarife (que antes mudava o saldo sem deixar rastro nenhum) e a compra lançada no Centro de Custo.
⚠️ Se o cadastro tinha menos do que ele pegou de verdade, o app avisa que vai ficar negativo e deixa registrar assim mesmo — o que vale é o balde que saiu da prateleira; o negativo mostra onde o cadastro está atrasado.
🔒 Mesma trava da entrada: relê o estoque inteiro antes de gravar e mexe só naquele insumo. Rede fora? Avisa e não inventa baixa — a produção não para por causa disso.
O livro começa agora: movimento feito antes desta versão não tem registro.
🖨️ Reservar clichê e faca voltou a ser só do painel central. O app do Desenvolvimento no celular tinha esse botão, e não devia: o número sai do contador da fábrica e não volta atrás — é decisão de quem está no PCP com a tela inteira na frente, não de quem está no chão de fábrica com o aparelho na mão.
📱 O app continua marcando "chegou" quando a ferramenta volta (isso não gasta número), e avisa na tela que a reserva é no central em vez de simplesmente não mostrar nada.
📦 A compra agora ENTRA no estoque. Lançou 1 balde de AZUL DH 06 no Centro de Custo? O saldo do almoxarifado sobe na hora: 12,5 → 32,5 kg. A caixinha "Somar no estoque" mostra o saldo que vai ficar antes de você clicar — e dá pra desmarcar quando a compra ainda não chegou na fábrica.
↩️ Apagou o lançamento por engano? Ele pergunta se quer tirar de volta do estoque. Quem apaga decide; sozinho ele não mexe.
🔒 Nunca grava por cima do estoque velho: na hora de somar, o sistema relê o almoxarifado inteiro e mexe só no saldo daquele insumo — se alguém deu baixa pelo celular no meio do caminho, a conta sai do saldo de verdade. Se a API falhar, ele avisa e pergunta se você quer lançar só o custo.
📱 O app do Almoxarifado passou a reler sozinho (ao voltar pra tela e de minuto em minuto) — antes um celular esquecido aberto na bancada gravava a cópia velha por cima e a compra sumia.
Cada lançamento que entrou no estoque fica marcado com 📦 no estoque na lista do mês.
🎨 Lançamento de Insumos agora puxa do estoque. Escolheu "O que comprou = Tinta", aparece o seletor com as tintas do almoxarifado (AZUL DH 06, PRETO 01…). Você escolhe, diz a quantidade — 1 balde ou 20 kg — e o valor sai sozinho pelo preço do cadastro.
📦 Vale pra todo insumo, não só tinta: cola, fita, faca, parafuso… o que estiver cadastrado no almoxarifado aparece na lista, com o saldo de hoje do lado.
✏️ No app do Almoxarifado, o cadastro do insumo ganhou preço por unidade pra qualquer categoria (antes só tinta tinha) e o campo "quanto vem em 1 balde/saco" — é ele que faz a conta do balde.
Nada trava: dá pra deixar em "— outro —" e digitar o valor na mão como sempre. O lançamento não mexe no saldo do almoxarifado — só lê o cadastro.
🛡️ A pose só vale se alguém cadastrar. Na v2.37.167 o sistema herdava a pose do desenho do gerador — e 3 caixas reais (NACON 10, NACON 11, TCHETTO 06) têm 2 poses desenhadas. Resultado: elas começaram a multiplicar sozinhas, sem ninguém pedir. O pedido 23646 do NACON passou a contar 11.760 cx de material num pedido de 5.000.
✅ Agora só multiplica o que está digitado no campo "Poses por chapa". O desenho virou sugestão: o aviso diz "o desenho tem 2 poses — clique ↻" e o botão só preenche com um clique consciente.
🔐 E abrir a caixa pra mexer em outra coisa não cola mais a pose sem querer — o campo mostra só o que está salvo.
Quem já usa corte e vinco: nada multiplica até você cadastrar a pose caixa por caixa.
v2.37.168 APP NOVO
04/08/2026
📱 App do Desenvolvimento no celular. Registrar amostra é trabalho de quem está em pé, com a caixa na mão, ao lado da balança — e fazer isso no painel central era desconfortável.
📷 O app abre no funil e o botão grande é "Registrar amostra": os dois botões de foto chamam a câmera direto. A foto de teste fica com borda laranja pra não confundir com a da amostra (ela é interna, o cliente nunca vê).
🏷️ Também dá pra mandar o link por WhatsApp, imprimir a etiqueta com QR e marcar quando o clichê e a faca chegam — tudo do celular. Instala igual aos outros apps.
🩺 Erro que virou instrução: quando o servidor sobe mas a migração ainda não rodou, a tela dizia só "Erro interno". Agora diz o que falta fazer, e o cliente que abrir o link vê um recado educado em vez de erro cru.
O app fala com as mesmas rotas do módulo — nenhuma regra nova.
✂️ A chapa da Corte e Vinco agora se multiplica pela POSE. No cadastro da caixa tem o campo Poses por chapa (só em corte e vinco, já preenchido pelo desenho). Com 2 poses, 1 chapa vira 2 caixas quando passa na máquina.
👷 Na máquina o operador digita CHAPAS — a tela mostra a conta ao vivo (“999 chapas × 2 poses = 1.998 caixas”) e é isso que vai pra coladeira. As perdas dele são em CAIXA, não em chapa (ele conta a caixa com defeito): 1.998 − 18 = 1.980 boas.
📋 A conta de material parou de acusar falta que não existe. Pedido de 2.000 cx com 1.000 chapas de 2 poses: o card mostra “1.000 chapas × 2 = 2.000 cx ✓”, a meta do operador vira 2.000 e a onduladeira é programada pra 1.000 chapas (caixas ÷ poses ÷ cortes), não 2.000.
📊 A barrinha do card diz o que está medindo: com pose vira “✂️ Caixa (Corte e Vinco · 2 poses)”, e o nome da máquina agora vem do pedido.
📄 Importar ficha (PDF/XLS) não puxa mais cor nem a nomenclatura deles. A ficha trazia as 4 cores e ainda cadastrava cor nova sozinha — parou. Quem põe cor é o cadastro da caixa, na mão (e a cor que a caixa já tinha não é mais apagada na reimportação).
🏷️ O código da caixa vem do nome do arquivo, não da descrição do PDF (“CX - CLIENTE - 01 VERDE SLIM”). Salve como “KININO CX 29.pdf” e sai CX 29. Na revisão o código virou campo editável.
✂️ Botão “Importar Corte e Vinco (lote)” saiu da tela de cadastro de caixas.
🛡️ Vale também nos pedidos que já estão abertos (lê a pose do cadastro da caixa, só do mesmo cliente). Caixa que não é corte e vinco continua exatamente como era: 1 chapa = 1 caixa.
v2.37.166 MÓDULO NOVO
04/08/2026
🧪 Desenvolvimento de Amostras — a aba nova em Comercial. Produto novo agora tem um lugar só, do registro da amostra até virar pedido, sem depender de quem lembrou de cobrar o quê.
🔗 O cliente aprova por um link. Ele abre no celular, vê medidas, material e preço, e aprova (ou pede ajuste) — e fica registrado quem aprovou, com cargo, data e hora.
📦 Amostra física com QR. A etiqueta sai com QR: o cliente aponta a câmera, confere que é a amostra certa e aprova ali mesmo.
🎨 Arte com marcação. Ele abre a arte, desenha com o dedo em cima do que precisa mudar e manda de volta. A JP recebe a imagem marcada e os anexos.
🖨️ Clichê e faca com numeração única. A reserva do número passou a ser feita no servidor — o Gerador de Etiquetas e o módulo novo pedem no mesmo lugar, então duas pessoas clicando junto não levam mais o mesmo número.
🚀 O vendedor lança o pedido quando a caixa é liberada, e o pedido entra avisando se clichê ou faca ainda não chegaram.
Tudo é acréscimo — nada do que existia mudou. ⚠️ Depende do Luan rodar a migração 024 e reiniciar o servidor; até lá a aba avisa que a rota ainda não subiu.
🧭 O contorno agora fecha nos DXF de verdade. Na v2.37.163 o palete continuou saindo quadrado nas caixas reais: o jeito de emendar era ingênuo demais. O arquivo do ArtiosCAD traz os riscos fora de ordem, uns ao contrário, com junção em T, furo/janela por dentro e ponta que não casa no dígito exato — bastava uma virada errada e o contorno não fechava.
🖐️ Agora ele começa no ponto mais à esquerda (que está sempre na borda de fora) e anda sempre virando pro mesmo lado, como quem atravessa um labirinto com a mão na parede: nas junções escolhe pelo ângulo, então não erra a volta. Ponta com sobra de até 0,5 mm é costurada, furo de dentro é ignorado, e se o corte sozinho não fechar ele tenta de novo contando o picote (caixa com aba destacável).
🔎 E quando mesmo assim não fechar, o desenho avisa: embaixo da vista de cima aparece "contorno não fechou" em vez de deixar você adivinhando por que saiu retângulo.
Passou nos 7 casos de teste (embaralhado, invertido, junção em T, furo interno, ponta com folga, polilinha fechada e contorno quebrado — esse último tem que recusar mesmo). Só desenho.
🪚 Agora o palete sai RECORTADO de verdade. Desde a v2.37.157 o desenho da faca era riscado por cima de um bloco retangular. Agora o sistema emenda os riscos de corte do DXF até fechar o contorno e usa essa silhueta como a forma da peça — na vista de cima e nas duas perspectivas 3D. As abas e os recortes aparecem no monte: a pilha fica com o perfil da caixa, não um tijolo.
🪶 E não pesou: cada amarrado sai em um caminho de desenho só (não em dezenas de peças), então o palete inteiro renderiza em ~7 milissegundos — o mesmo de antes.
🛟 Se o contorno do DXF não fechar (risco solto, pedaço faltando) ou vier sem tamanho, ele volta sozinho pro desenho antigo, sem travar nem sumir — e os vincos e o picote continuam tracejados por cima.
Continua só pra caixa marcada como "📏 Caixa vai ABERTA" com DXF no projeto. Só desenho — não muda conta nenhuma. Junta com os consertos do desenho da v2.37.159.
👻 Pedido sumindo da fábrica: resolvido. O pedido guarda o nome da 1ª máquina, e o app do operador casava esse nome letra por letra. Pedido gravado como "Slotter" (em vez de "Máq. B Slotter") não casava com ninguém e sumia da tela de todo mundo, calado — foi o que aconteceu com o KININO CX 05: 20.000 chapas prontas e o operador sem ver o pedido.
🔎 De onde vinha: do orçamento convertido em pedido. Na conversão o código gravava o apelido curto ("Slotter"), que serve pro cronograma mas não serve pro operador — a caixa já nascia com o nome completo e só o pedido ficou pra trás. Corrigido na origem: agora nasce "Máq. B Slotter" / "Máq. A Corte e Vinco".
🔤 O sistema também passa a entender o apelido: "Slotter" = Máq. B Slotter, "Corte e Vinco" = Máq. A Corte e Vinco. Vale na hora de publicar pro operador, então os pedidos antigos voltam a aparecer sozinhos — sem reeditar um por um. Máquina cadastrada (offset, acopladeira…) continua mandando no próprio nome.
⚠️ Aviso na linha do pedido. Se a 1ª máquina não existir no cadastro, a linha avisa "máquina fora do cadastro — nenhum operador vê". Antes só dava pra descobrir abrindo o pedido — e o menu ainda mentia dizendo "(inativa)", quando na verdade a máquina não existe.
🕐 Operador de horário livre entra a qualquer hora. Turno com início igual ao fim ("00:00 às 00:00") era lido como turno de verdade e barrava o operador o dia inteiro com "⛔ Fora do seu horário de acesso". Agora início = fim significa horário livre: entra sempre e o app não fecha sozinho. O cadastro também parou de gravar isso como turno.
Só no site. Não precisa do Luan.
📦 O Almoxarifado da Cartonagem também sugere o fornecedor. No app Almox · JP Embalagens, os dois campos "Fornecedor" — o do insumo e o da solicitação de compra — deixaram de ser texto solto e passam a sugerir quem está no Cadastro de Fornecedores.
🎯 A sugestão segue a categoria do item: Tinta puxa quem vende tinta, Faca quem vende faca, Parafuso quem vende peças, Ferramenta quem vende ferramentas. Na solicitação, se tudo na lista for da mesma categoria ele filtra igual; se for misturado, mostra todos.
✍️ Continua dando pra digitar um nome novo na mão — nada trava. Quem cadastra fornecedor continua sendo o PCP, no sistema; o almoxarifado só lê.
Só no app do almoxarifado. Não precisa do Luan.
🏪 Cadastro de Fornecedores. Tela nova em Cadastros → 🏪 Fornecedores: um lugar só pra guardar todo mundo de quem a fábrica compra — tinta, cola, fita de arquear, grampo, clichê, faca, papel, chapa, peças, palete, EPI, frete, serviços…
🏷️ Em cada fornecedor você marca o que ele fornece (pode marcar vários) e guarda contato, telefone/WhatsApp, e-mail, CNPJ, cidade e condição de pagamento. O telefone vira link do WhatsApp — é só clicar.
✍️ O campo "Fornecedor" parou de ser texto solto. No Lançamento de Insumos (Centro de Custo), quando você escolhe "O que comprou = 🎨 Tinta", o campo já sugere só quem vende tinta. Também sugere em Compras (ordem de compra), no cadastro de papel e na entrada manual de chapa. Continua dando pra digitar um nome novo na mão — nada trava, e os nomes já usados antes continuam aparecendo.
🚫 Quem parou de fornecer: desmarque "Ativo" em vez de excluir — ele some das sugestões e o histórico fica intacto.
Roda no sistema (PCP). Não precisa de banco novo nem do Luan.
🔁 O aviso do palete em caracol dizia a volta errada. No padrão caracol (cata-vento) a camada de cima entra girada 90°, mas a legenda mandava girar 180° — o desenho estava certo e o texto errado. Quem monta olhando a frase montava torto. Nos outros padrões continua 180°, como sempre foi.
📐 Palete sumia da tela quando a folga não era múltipla de 5. Digitar folga 12 (ou 3, ou 12,5) apagava o palete inteiro e aparecia "preencha as medidas" com tudo preenchido. Agora qualquer valor funciona.
✂️ Recorte do DXF sumia calado. Se o desenho da faca viesse sem medida, o contorno simplesmente não aparecia e nada avisava. Agora o palete desenha normal e o recorte só entra quando o desenho está bom.
🎨 Cliente com muitas caixas na mesma carga ficava invisível no planejamento. A partir da 7ª caixa do mesmo cliente a cor ia escurecendo até virar preto, e da 8ª em diante o quadradinho sumia da planta. Agora os tons alternam claro/escuro e dá pra distinguir todos.
Tudo desenho e aviso de tela — nenhuma conta de produção, estoque ou carga mudou.
🧊 O recorte do DXF agora aparece também nas perspectivas 3D. Na v2.37.157 ele só saía na vista de cima; agora a tampa dos pacotes — tanto na 1ª camada quanto no palete completo — mostra o contorno da faca com os vincos e o picote tracejados, deitados na perspectiva junto com o pacote (peça girada 90° sai girada também).
👁️ Só a camada de cima recebe o desenho — as de baixo ficam tapadas pela camada seguinte, então desenhar nelas só ia pesar e sujar a imagem.
Continua valendo só pra caixa marcada como "📏 Caixa vai ABERTA" com DXF no projeto. Só desenho — não muda conta nenhuma.
✂️ O desenho do palete agora acompanha o recorte do DXF. Na vista de cima, a caixa que vai aberta deixou de ser um retângulo azul: aparece o contorno de verdade da faca — abas, recortes e travas do jeito que estão no arquivo —, com os vincos tracejados em azul e o picote tracejado em laranja, exatamente como no desenho do projeto de Corte e Vinco.
🔄 Peça deitada 90° no lastro sai desenhada girada junto, então dá pra ver na hora se o encaixe do palete faz sentido. Embaixo do desenho fica escrito "recorte do DXF" pra você saber que aquilo é a peça real, e não um retângulo.
📐 Vale pra qualquer caixa marcada como "Caixa vai ABERTA" que tenha DXF no projeto. Sem DXF (ou caixa colada/grampeada) continua o retângulo de sempre.
Só desenho, no cadastro de caixa. Não muda conta nenhuma nem precisa do Luan.
📏 Paletização: a caixa que vai ABERTA agora conta certo. A conta antiga — chapa ÷ 2 − 35mm — é da caixa maleta que sai colada (ou grampeada): ela é dobrada ao meio, então ocupa metade do comprimento e 2 espessuras de altura. A caixa de corte e vinco sem acabamento sai plana pro cliente — nela essa conta não vale.
✂️ Agora, nessas caixas, o palete usa a peça de verdade da faca: o molde do DXF do projeto (ou, na falta dele, a chapa menos o refile), e cada peça conta 1 espessura de onda, não 2. Exemplo real: chapa 641,3 × 650,9 com refile 30 × 30 → a peça no palete é 611,3 × 620,9 mm (antes o sistema empilhava uma caixa "dobrada" de 303 × 651 que não existe).
✅ Ele já marca sozinho um ✓ novo "📏 Caixa vai ABERTA" quando a caixa é corte e vinco e está como Sem fechamento. Dá pra marcar/desmarcar na mão em qualquer caixa (fica salvo na caixa), e o que estiver valendo aparece escrito em cima do desenho.
🔒 Nada muda nas caixas coladas/grampeadas — quem não está marcado continua com a conta de sempre.
Só no cadastro de caixa (paletização). Nada de servidor — não precisa esperar o Luan.
🔔 Os avisos do sistema agora aparecem no ALTO da tela e na frente de tudo. Antes o aviso nascia pequeno no canto de baixo, à direita — sumia atrás de qualquer janela aberta (e até atrás da barra do Windows), então dava pra ver que "piscou alguma coisa" mas não dava pra ler o motivo.
👀 O que mudou: o aviso vem no topo, no meio, em letra maior, com ✅ quando deu certo e ⚠️ quando deu erro; erro fica 9 segundos (o normal, 3,5s) e o texto não é mais cortado — mensagem comprida quebra em várias linhas e aparece inteira. Dá pra clicar no aviso pra fechar na hora.
🧾 Todo aviso também fica registrado no console (F12) — se ainda assim passar batido, dá pra ler o motivo depois.
Só visual, só no sistema (PCP). Não mexe em dado nenhum e não precisa do Luan.
🧰 Mutirão na Perda por Etapa. A lista dos pedidos que não fecham virou bancada de trabalho: cada linha mostra a escada inteira (pedido → onduladeira → slotter → fechamento), o que não bate, e tem campo pra digitar a chapa certa + ✔️ pra gravar. Fica registrado na vida da caixa (quem corrigiu, quando, de quanto pra quanto).
🚫 “Não dá pra recuperar” — quando ninguém souber mais o número daquela rodada. O pedido sai da lista e passa a ser contado à parte, sem entrar em média nenhuma. Dá pra voltar atrás depois (↩).
🔢 O campo é em CHAPA e a escada é em CAIXA — então ele mostra a conta na hora (“3.334 chapas × 3 cortes = 10.002 caixas”) e a sugestão em azul já vem em chapa. Essa sugestão é o mínimo que a onduladeira precisou ter feito, não é a verdade: ela só preenche o campo quando você clica.
Nada é corrigido sozinho, de propósito. O número real daqueles pedidos não existe mais em lugar nenhum (o lançamento antigo substituía, o papel lido nunca foi preenchido e o consumo de bobina não ficou gravado). Preencher tudo com estimativa faria a tela dizer “perda zero” justamente onde não se sabe de nada — então quem sabe é quem digita.
🌀 Quando o pedido roda de novo, a chapa agora SOMA. Até aqui o lançamento da onduladeira substituía o número: se o pedido voltava e rodava outra vez, ficava valendo a chapa da primeira rodada — e a produção das duas aparecia contra a chapa de uma só.
👉 Com chapa já lançada, o painel pergunta em um toque: ➕ Rodada nova (soma no que já tinha) ou ✏️ Corrigir o número (troca o total). Antes de lançar ele mostra quanto vai ficar — “vai ficar 10.200 chapas (6.000 de antes + 4.200 agora)”. Primeiro lançamento do pedido continua igual, um toque só.
📋 Vale nos dois caminhos: no painel da onduladeira e no “Chapa produziu” do PCP. Cada rodada fica registrada no pedido (quem lançou, quando e quanto).
Por que importa: era esse o motivo de 57% dos pedidos caírem em “número não fecha” na Perda por Etapa — a conta comparava duas rodadas de produção com a chapa de uma. De quebra, a meta do operador na tela dele passa a bater com o material que realmente entrou. E o número da versão nos apps da onduladeira, bobinas, escala, motorista, vendedor e almoxarifado voltou a acompanhar — estava congelado na v2.34.45 na telinha (a atualização automática sempre esteve certa).
🔻 A Perda por Etapa agora conta a história inteira do pedido. Abrindo o pedido você vê, degrau por degrau:
🌀 A onduladeira saiu acima ou abaixo do pedido — quantas caixas e quantos % (verde acima, vermelho abaixo).
🖨️ Quanto o slotter / corte e vinco apontou e quantos % ficaram pra trás em relação ao que entrou, com a máquina, o operador e o dia do apontamento.
📦 Quanto perdeu na coladeira / grampeadeira E POR QUE — o motivo vem do que a fábrica já aponta: perda de ajuste, perda de produção e ocorrência (com a máquina e a descrição). Cada degrau mostra quantas caixas da perda já têm motivo apontado e quantas ninguém explicou.
📥 Quanto foi pro estoque de verdade (caixa dos paletes confirmados) e quanto ainda está lá hoje — e o R$ que aquele pedido deixou de ganhar.
📅 Períodos novos: hoje, ontem, semana, mês, ano e personalizado (escolhe de/até). E as tabelas agora são por dia, por semana, por mês e por ano — todas com a coluna do que foi pro estoque.
🔻 Tela nova: Perda por Etapa (Análises). O pedido vira uma escada: saiu da onduladeira → passou no slotter → fechou na coladeira/grampeadeira. Em cada degrau ela mostra quantas caixas ficaram no chão, quantos % isso dá e quanto R$ deixou de entrar — por pedido, por semana, por mês e por cliente.
🎯 Tem o "onde a caixa some" (qual passagem come mais caixa) e, clicando no pedido, a escada dele com o número de cada máquina.
🔎 E diz quanto da fábrica está dentro da conta: de todos os pedidos que produziram no período, quantos % dá pra medir, quantos ficaram de fora porque o número não fecha e quantos só têm uma etapa apontada — em pedidos e em caixa pronta.
Números da própria fábrica: onduladeira = chapas boas lançadas no painel da onduladeira × cortes; as outras etapas = apontamento do operador; caixa pronta = a mesma conta do Estoque. Pedido em que a etapa de depois aponta mais caixa do que entrou (quase sempre rodou de novo e a chapa não foi relançada — o lançamento substitui, não soma) fica fora da média, numa lista à parte pra arrumar na origem.
📦 Tela nova: Almoxarifado · Cartonagem (aba Cadastros). Mostra aqui no sistema o mesmo estoque do app do almoxarifado — tinta, faca, cola e insumos — com saldo, mínimo, preço e quanto tem parado em R$, filtro por categoria, busca e os pedidos dos operadores no topo.
🎨 As 56 tintas da tabela SILRESIN entraram com preço (27/07/2026). E tem o ligador: a cor do cadastro tem nome curto ("PRETO 01") e a do fornecedor tem nome completo ("PRETO DH 001") — você escolhe qual é qual num seletor, que já mostra as parecidas primeiro, e o preço por quilo entra na cor. É isso que faz o custo de tinta do orçamento deixar de sair zerado.
🧹 Excluir cor passou a apagar de verdade. O botão tirava da tela mas o registro voltava no carregamento seguinte (a gravação só sabia inserir/atualizar, não apagar). Foi criada a rota de exclusão e, enquanto ela não sobe no servidor, a cor é escondida das listas. Os 11 nomes quebrados que uma importação antiga de PDF deixou ("Total", "do", "Medidas", "Riscador"…) já sumiram.
📏 A chapa da maleta agora usa o lap de cada caixa + o refile. Antes o sistema somava 50 mm fixo pra toda maleta. Na verdade são duas coisas: o lap (aba de cola — no padrão da fábrica 35, mas cada caixa tem o seu no cadastro) mais o refile de 15 mm no comprimento. 35 + 15 = 50, por isso o número antigo batia na maioria — mas escondia os dois e ignorava quem tem lap diferente.
Conferido contra as 104 maletas cadastradas: 9 caixas ficaram mais próximas do que está no cadastro (as de lap 45 e 50, do FK Grupo) e o resto não mudou. A linha de referência da caixa agora mostra o lap + refile usados. Caixa sem lap cadastrado continua com o padrão 35.
🤝 Vendedor no orçamento. Novo campo no cabeçalho, ao lado do IPI: ele já vem do cadastro do cliente e dá pra trocar só naquele orçamento. O nome sai no documento do cliente (tela, PDF, WhatsApp) e viaja pro app do vendedor junto com o orçamento.
📐 A maleta agora tem o desenho de verdade (FEFCO 0201) — igual o corte e vinco já tinha. Aparece a aba de cola, os quatro painéis C · L · C · L, as abas de cima e de baixo, o vinco (verde tracejado), o corte (preto) e as medidas de cada painel mais o total da chapa. Antes eram três faixas azuis sem medida nenhuma.
📦 O orçamento agora puxa a caixa inteira do cadastro. Escolheu a caixa e já vem: chapa (o material), cores da impressão, clichê, faca e o R$/kg que ela pratica — além das medidas e do estilo, que já vinham. Em caixa de corte e vinco vem também a chapa em mm e o refile.
✍️ Não atropela o que você digitou: só preenche campo vazio. E aparece embaixo, em verde, a lista do que veio do cadastro, pra você conferir e ajustar se este orçamento for diferente.
💵 No orçamento, dá pra digitar o preço da caixa direto — igual no cadastro. O R$/kg se ajusta sozinho (preço ÷ peso). Antes só dava pra ir pelo R$/kg: pra fechar num preço combinado com o cliente, era tentativa e erro.
📋 Botão "Usar preço do cadastro". Se a caixa já tem preço cadastrado (o último que foi feito pra ela), aparece um botão verde com o valor — um clique e ele entra, com o R$/kg recalculado.
⚠️ O aviso de preço abaixo do nominal ficou de verdade. Saiu a caixinha branca do navegador e entrou um alerta vermelho e laranja, mostrando lado a lado o seu R$/kg, o nominal da chapa e quanto falta (em R$ e %), com "Voltar e corrigir" ou "Continuar assim".
🖱️ Arrastar pra cima parou de "grifar" a tela. Ao puxar o pedido para cima, o navegador começava a selecionar o texto (aquele azulão) em vez de mover o item. Agora o texto do card não é selecionável — só o campo do número — e o arrasto sobe liso.
⚡ E ficou mais leve pra trocar de lugar: antes era preciso empurrar o pedido uma linha inteira pra ele pular a posição; agora ele troca assim que passa da metade do vizinho, subindo e descendo posição a posição enquanto você move.
✋ Arrastar a ordem de produção ficou de verdade. Agora o pedido que você segura salta pra frente e acompanha o mouse; os outros abrem espaço na hora, deslizando pro lugar. Solta e ele encaixa.
🟢🔴 Fica claro quem está na sua mão: o pedido pego ganha borda verde e os outros ficam com borda vermelha enquanto você arrasta. Os números vão se ajustando ao vivo, conforme ele sobe ou desce.
🏗️ O orçamento agora mostra a chapa por inteiro. Em cada item do documento que vai pro cliente (tela, impressão/PDF, WhatsApp e e-mail) saiu uma linha só da chapa: código · onda · gramatura · resistência à coluna (kgf). Antes só aparecia o código da chapa, e a coluna — que é o que o cliente pergunta — ficava de fora. Orçamento antigo que não gravou a coluna puxa do cadastro da chapa na hora de mostrar.
🖼️ A logo da JP entrou no cabeçalho do orçamento. Ele usa a logo cadastrada em Cadastros → Dados da Empresa (a mesma da Ordem de Compra), junto com o nome e a cidade de lá. Enquanto não tiver logo cadastrada, continua o quadrado azul "JP" de sempre.
Só mexe na tela do orçamento. Nada de servidor — não precisa esperar o Luan.
🔢 Ordenar a produção ficou fácil. Agora dá pra digitar o número da posição e apertar Enter — o pedido pula direto pra lá (antes era clicar ↑ um por um até chegar). E o arrastar foi refeito: segura e puxa, uma linha azul mostra onde vai cair, e funciona no tablet/celular (o antigo só pegava no mouse).
👆 Clique na barra do cronograma pra ver o detalhe. Clicou na barra da máquina, ele desce até o card daquele pedido e pisca — ali estão o horário real, a duração, a velocidade, as paradas e o que o operador apontou.
⏰ O app do operador agora fecha o turno sozinho. Faltando 20 minutos pro fim do turno dele, aparece um aviso grande (com som) pra ir fechando o pedido, e uma faixa com a contagem fica no rodapé. 5 minutos depois do horário, o app fecha sozinho: a produção do operador é gravada no nome dele e o pedido fica liberado pro próximo operador continuar de onde parou. Quem está de hora extra toca em "mais 15 min" — e isso fica registrado no log de acessos.
🕐 O horário vem do cadastro do operador (Operadores → 🕐 Turno). Operador sem turno cadastrado não muda nada — o app se comporta igual a antes.
⏱ Tolerância de 30 min pra hora extra. O horário do cadastro também é a trava de entrada: quem tentava logar fora do turno era barrado seco. Agora ele ainda entra até 30 minutos depois do fim do turno — o acesso fica marcado como "⏱ entrou em hora extra" no log e o app não fecha na cara dele. Tocando na faixa amarela do rodapé, estica mais 15 min.
🔄 Finalizar com material sobrando devolve o pedido pra fila. Antes, "Finalizar" encerrava a etapa e o pedido sumia da lista, mesmo com chapa sobrando. Agora o app confere o saldo da etapa (a chapa lançada, ou o que a etapa anterior liberou): pedido de 10.000 com 5.000 de chapa em que o operador 1 fez 2.000 → sobram 3.000, então ele escolhe "GRAVAR e PASSAR pro próximo operador": as caixas dele são creditadas, as etiquetas do lote saem, e o pedido volta pra lista pro operador 2 terminar. Se não sobra material, o "Finalizar" encerra a etapa de vez, como sempre.
Só mexe no app do operador. Nada de servidor — não precisa esperar o Luan.
🧑🏭 O nome do operador voltou pra etiqueta. Quando o PCP reimprimia a etiqueta (pelo "🖨️ imprimir e liberar" ou pelo Estoque PA), o campo OPERADOR saía com um traço — porque quem estava clicando era o PCP, não o operador. Só que o nome sempre esteve no lançamento de produção: agora a etiqueta busca lá. Se o pedido foi feito em dois turnos, cada lote sai com o operador daquele lote.
🔒 Palete que já saiu não pode mais ser corrigido por trás. O sistema já barrava corrigir a quantidade de um palete bipado, mas não pegava os outros casos — palete baixado à mão no PA ou que foi numa carga montada no PCP passavam batido, e a correção mudava o estoque de uma carga que já tinha ido embora. Agora o servidor barra os três caminhos, e diz qual foi e quem deu a baixa.
🛡️ O registro de saída dos paletes virou à prova de sobrescrita. O documento onde ficam as saídas agora só aceita gravação palete a palete: nenhum aparelho consegue mandar a lista inteira por cima e apagar o que os outros gravaram — o servidor recusa.
As duas últimas dependem do Luan reiniciar a API. Até lá tudo continua funcionando como antes — nada quebra.
👀 Agora dá pra VER quando saiu só parte do pedido. A saída por palete já funcionava, mas o número simplesmente caía e ninguém sabia por quê. Agora:
🗂️ Na Vida da Caixa tem uma estação nova, "Saída do estoque", com cada palete que saiu — número, lote, quantas caixas, quem tirou, quando e por qual caminho (baixa manual, bipado na expedição ou carga do caminhão). Ela avisa em amarelo quando sobrou palete no estoque e em verde quando o lote saiu inteiro.
🏷️ No PCP, o pedido com saída parcial ganhou o selo "📤 3 de 4 paletes ainda no PA", do lado do selo de estoque que já existia.
🧾 O romaneio agora confere com o palete de verdade. Ele calculava as caixas pela paletização do cadastro; quando a carga leva todos os paletes daquela caixa, ele passa a somar o que existe de fato no estoque, sem calcular nada. (Nos números de hoje dá exatamente o mesmo — a diferença aparece quando algum palete foi corrigido na mão.)
Fecha o módulo de saída por palete: agora ela acontece, converge entre os computadores e aparece onde você procura.
🛟 Fim do "carreguei 1 palete e sumiram 4". Quando a carga levava só parte dos paletes de um pedido, o lote inteiro desaparecia do Estoque PA — o saldo que ficou na fábrica virava fantasma. E, do outro lado, palete bipado não casava com o estoque, então não dava baixa nenhuma. Os dois errados, em direções opostas. Agora a baixa é palete a palete, em todos os caminhos (manual, bipagem e carga), e o pedido só vira "carregado" quando o último palete sai. Se sobrou palete, ele continua no estoque e no plano de carga.
🛡️ O app da Expedição não reescreve mais o estoque. Este é o mais importante e ninguém tinha visto: a cada "Caminhão carregado!", o app gravava a lista de caixas por cima do documento inteiro do estoque — o que descartava o estoque de chapas e TODO o histórico de movimentações do servidor, e ainda jogava a lista da memória daquele aparelho por cima do que o PCP tivesse acabado de salvar. Agora ele só registra os paletes que saíram, cada um na sua chave, e nunca sobrescreve nada de ninguém.
Isso fecha o módulo de saída por palete: a mesma chave em todos os caminhos, sem baixa dobrada e sem apagar o trabalho do outro computador.
🔫 Bipou o palete, ele sai do estoque na hora. Antes a bipagem do empilhadeirista só marcava o palete no plano de carga: no Estoque PA ele continuava lá, como se ainda estivesse na fábrica, até alguém finalizar a carga — e aí sumia o lote inteiro de uma vez. Agora o bip e a baixa manual (📦) são a mesma coisa: apontam pro mesmo palete, pelo número do QR da etiqueta. Não tem como dar baixa dobrada.
📡 Bipagem que ficou presa no aparelho não se perde. O PCP confere sozinho, de minuto em minuto, se todo palete bipado já saiu do estoque — então bipagem feita sem internet (que só sobe depois) e carga bipada antes desta versão também entram na conta.
↩ Bipou errado? O ↩ do 📦 devolve o palete pro estoque e ele não volta a sair sozinho. O aviso lembra de conferir com a expedição se o palete realmente não foi no caminhão — a bipagem continua marcada no plano de carga.
Conferido nas 23 bipagens que já existem no sistema: todas casam com o palete certo, e nenhuma mexe no estoque de hoje (são de cargas já concluídas).
📦 Agora dá pra dar saída de UM palete, sem tirar o pedido inteiro do estoque. Antes era tudo ou nada: quando só um palete embarcava (a NACON mandou só o palete parcial de 347 cx do "32 CAMPO VERDE", dos 4 que tinha), ou sumia o lote todo do Estoque PA, ou não saía nada. Agora, no Estoque PA, cada linha tem o botão 📦: ele abre a lista dos paletes daquele lote, com o número e quantas caixas tem cada um — você marca os que saíram e pronto. O que fica aparece como "3 de 4" na coluna de paletes.
👀 A saída vale em todo lugar, na hora. O que sai do palete some do Estoque PA, do plano de carga, do romaneio, da programação e dos relatórios — e aparece nos outros computadores sozinho. Cada saída guarda quem deu baixa, quando e o destino, e fica no histórico de movimentações. Errou? Tem o ↩ voltar, que devolve o palete pro estoque.
🔗 Manual e bipagem são a mesma coisa. O palete é identificado pelo mesmo número do QR da etiqueta, então dar baixa à mão e bipar na Expedição apontam pro mesmo palete — não tem como dar baixa dobrada. Quando o último palete do lote sai, o pedido vira "carregado" sozinho, como antes.
O 🚚 continua existindo pra quando o pedido inteiro vai de uma vez. Próximo passo: o bip da Expedição também tirar o palete do PA na hora.
🧮 Romaneio contava palete pela metade como se fosse cheio. O último palete de um produto quase nunca fecha completo, mas o romaneio multiplicava todos os paletes pela paletização do cadastro. No romaneio da NACON, o "16 KIT FILME PRETO-B" saiu com 11.250 caixas quando no estoque são 10.349 — o 6º palete tem 974, não 1.875. Não era só esse item: 5 das 6 linhas estavam infladas, e o total do papel dava 35.625 cx / 6.766 kg em vez de 28.342 cx / 5.281 kg. Agora cada palete conta o que ele realmente tem, e o romaneio bate com o Estoque PA.
Romaneio gerado pela carga bipada já estava certo (lê a quantidade de cada palete). O erro era só no romaneio tirado do plano de carga. Romaneios já emitidos guardam os números antigos — reimprimir não corrige, precisa gerar de novo.
🤝 App do Vendedor mostrava status errado. O vendedor via um status e o sistema mostrava outro. Eram três furos: (1) bastava UM palete do cliente embarcar numa carga pra todos os pedidos dele virarem "Em rota de entrega" — o FK GRUPO tinha 41 pedidos "esperando programação" aparecendo como "em rota", e a KININO e a NACON também; (2) faltavam os status "Material disponível" e "Reprogramado" no app, os dois caíam em "Esperando programação" (a THINSOL 23654/900ML estava com 12.000 chapas na mão e o vendedor via "esperando" — material liberado agora aparece como "Produzindo", e "Reprogramado" ganhou fase própria); (3) numa entrega parcial, o saldo que voltava pra fila ficava travado em "em rota" pra sempre. Agora o app casa o palete pelo pedido exato (não pelo nome do cliente nem pelo nº, que se repete em entregas parceladas) e usa os mesmos rótulos do PCP. Conferido nos 238 pedidos reais: 100% batendo com o sistema.
📄 Romaneio não imprime mais pedido antigo. Quando o mesmo produto já foi entregue outras vezes, o romaneio listava todos os números de pedido daquela caixa — a NACON saiu com "23277, 23452, 23694" no "16 KIT FILME PRETO-B", sendo que os 6 paletes que estavam indo eram todos do 23694. Agora o romaneio olha de qual pedido saiu cada palete que está embarcando, e imprime só esse. Pedido já entregue nunca mais aparece no papel do cliente.
📦 Palete empilhado à mão aparece direito no desenho 3D. Quando você empilhava um palete em cima de outro pelo ajuste manual, ele às vezes era desenhado por baixo do palete de baixo — aparecia cortado, parecendo que estava atrás. Era só desenho (a carga e a bipagem sempre estiveram certas), mas atrapalhava a conferência. Nos planos já salvos eram 23 paletes fora de ordem; agora é zero.
📦 Caixa importada de ficha não some mais do cadastro. Ficha com código curto (a KININO "CX 29", por exemplo) entrava sem código — e caixa sem código não aparece na lista. Pior: quem tentava importar de novo escrevia por cima da anterior, então dava pra lançar 3 vezes e continuar existindo um registro só. Agora o sistema lê o código curto, e se a ficha não trouxer, tira do nome do arquivo ("KININO CX 29.pdf" → "CX 29").
⛔ Ficha sem código não salva mais. Em vez de entrar calada e sumir, o sistema barra e diz qual arquivo está sem código. Quando o código vier do nome do arquivo, aparece um aviso amarelo pra você conferir antes de salvar.
🖥️ Fim do "num PC funciona, no outro não". Quando um arquivo do sistema era atualizado, alguns computadores continuavam rodando a versão velha dele — sem erro nenhum na tela. Agora cada arquivo é carimbado automaticamente pelo seu próprio conteúdo, então é impossível sobrar um pedaço antigo.
Nesta atualização o app baixa o pacote inteiro uma vez (por causa do novo carimbo) e depois volta ao normal. A caixa da KININO já cadastrada sem código precisa ser corrigida na mão, no cadastro.
🩹 Computador que ficava com a tela velha se conserta sozinho. Um PC com o relógio adiantado gravava uma marca de "já sei disso" no futuro — e o sistema, achando que já tinha tudo, parava de buscar novidade até o relógio do servidor alcançar. Era isso que fazia o mesmo pedido aparecer concluído num computador e zerado no outro, e por isso na janela anônima funcionava (ela começa sem essas marcas).
🔄 Botão "Forçar atualização" no menu Ajustes: manda buscar tudo de novo na hora, sem esperar. Não apaga nada — só descarta as marcas de "já sei disso".
Vale pros 6 sincronizadores (pedidos, cadastros, operadores, caixas, clientes e listas em bloco). Se aparecer no console o aviso pedindo pra conferir o relógio, vale acertar a hora do computador — a correção destrava, mas o relógio certo evita o problema.
🎯 O limite da sugestão agora sai do próprio cadastro — cada máquina tem o seu. Não dá pra usar um teto fixo em cx/h porque tem máquina que roda muito mais que outra. Então a referência é a velocidade que você já cadastrou nessa caixa (ou o padrão da máquina): passou de 3× isso, é lançamento disfarçado e fica fora da sugestão.
Se a caixa/máquina ainda não tem velocidade cadastrada, nada é filtrado por teto — o sistema não inventa limite. E a sugestão nunca vai sozinha pro cadastro: só entra quando você clica em Usar.
🧭 O menu vem completo já no PRIMEIRO login. Antes, quem entrava pela primeira vez via só o módulo Produção com 5 itens (Dashboard, Relatório, PCP, Estoque e Chat) — Cadastros, Expedição, Análises, Comercial e Custos simplesmente não apareciam, e só voltavam depois de dar F5.
🔍 Por que acontecia: o menu só conferia as permissões no carregamento da página e em dois relógios fixos (1,3s e 2,9s). Como digitar e-mail e senha demora mais que isso, a última conferida rodava com ninguém logado ainda — e sem perfil ele só mostrava as 5 abas que já vêm abertas no HTML (das 65 que existem).
✅ Agora o menu se refaz no instante em que o login aplica o seu perfil, sem depender de relógio. Testado: passa de 1 módulo/5 abas para 6 módulos/60 abas na hora, sem F5.
De quebra, a caixa "Versão atual" aqui em cima estava travada na v2.37.125 desde o bump da 126 — voltou a acompanhar.
⚡ A sugestão de velocidade do cadastro parou de contar lançamento como produção. Quando alguém registra a produção inteira de uma vez (11.626 caixas em 1 minuto, por exemplo), aquilo não é medição — e estava puxando a sugestão pra números impossíveis. Agora registro com menos de 10 minutos fica fora da conta, e a caixa mostra quantos foram ignorados: "3 produções · 2 lançamentos fora da conta".
Nenhum registro é apagado e a produção continua contando normal — muda só a sugestão de cx/h do cadastro. No histórico da fábrica isso derrubou a média de 64.616 cx/h (impossível) pra 4.002 cx/h (o real).
🖨️ Consertado: imprimir a Ficha do Operador saía em branco. Agora ela abre numa página própria, em papel branco, com o cabeçalho da JP — máquina, dia, resumo do turno e cada pedido com tempos, velocidade, perdas e ocorrências. Sai limpo, sem os botões e filtros da tela.
⏱️ A "Média real" agora é do processo inteiro. Antes ela contava só a última máquina: um pedido que levou 1h na Slotter + 1h na Coladeira aparecia como 1h, e a média saía o dobro do que a fábrica realmente gasta. Agora soma as máquinas por onde a caixa passou — 10.000 cx em 1h+1h = 5.000 cx/h, o custo real de máquina.
A quantidade continua sendo a da etapa final (caixa pronta não conta duas vezes). Isso corrige números impossíveis que apareciam na carteira, tipo 147.400 cx/h.
⚡ Cada caixa com a sua velocidade. No pedido, o histórico de cx/h estava vindo do cliente — todas as caixas da DEUSA mostravam o mesmo número (01.02 igual à 02.01). Agora ele é desta caixa (cliente + código + máquina).
Se a caixa ainda não tem histórico, o número do cliente continua aparecendo — mas escrito "média do cliente", pra você não confundir com o dela. O cadastro da caixa (seção 9 · velocidades por máquina) já era por caixa e não mudou.
🏭 O roteiro aparece no card do pedido. O card já mostrava a máquina quando o pedido tinha roteiro próprio — só que pedido antigo (importado antes de ontem) não tinha, e o card ficava mudo. Agora, quando o pedido não tem roteiro próprio, o card mostra o roteiro do cadastro da caixa, com uma marquinha · cadastro do lado pra você saber que aquilo ainda não foi decidido naquele pedido.
👀 Fica assim no card: 🅱️ Máq. B Slotter → 🧩 Acopladeira → 📦 Coladeira. Caixa sem roteiro cadastrado continua sem mostrar nada, como antes — e nada disso grava no pedido, é só o que você está vendo.
🏭 A máquina agora fica definida no cadastro da caixa. Na seção 7 · Clichês, faca e fechamento tem um bloco novo, Roteiro de produção — por onde essa caixa passa: você escolhe a 1ª máquina (Slotter, Corte e Vinco ou uma cadastrada) e, se precisar, processos do meio (acopladeira, verniz…). O Fechamento que já existia continua sendo a última máquina. Um desenho do fluxo mostra o caminho completo até a Expedição.
✅ Pra que serve: todo pedido novo dessa caixa já nasce com a máquina certa — tanto o lançado na mão (ao escolher a caixa o roteiro se preenche sozinho, com um aviso verde de onde veio) quanto o importado do relatório. Antes o PCP tinha que escolher máquina de pedido em pedido.
🔒 Não mexe em pedido que já existe: só vale pra pedido novo, e dá pra mudar na hora se aquele pedido específico for diferente. Caixa sem roteiro preenchido continua exatamente como era.
✂️ Caixa de Corte e Vinco sem máquina escolhida vai automático pra Máq. A (nunca mais cai na Slotter por engano) e o cronograma passou a entender o fechamento das caixas com roteiro em sequência.
📷 Ficha do Operador: a foto da ocorrência abre com um clique. A ocorrência que tem foto agora fica destacada — clicou, a foto aparece em tela cheia com a descrição. Fecha no ✕, clicando fora ou no ESC.
🖨️ Ficha do Operador ganhou o botão Imprimir. Imprime ou salva em PDF só a ficha da máquina do dia (sem os filtros e botões da tela) — pra arquivar ou levar pro chão de fábrica.
📱 Sistema muito melhor no celular. Três coisas que atrapalhavam:
↔️ Agora dá pra arrastar a tabela pro lado. Em telas como Máquinas/Processos a última coluna ficava cortada e inalcançável — não tinha como chegar nela de jeito nenhum. Agora a tabela desliza com o dedo.
🏷️ Os números voltaram a dizer o que são. Nas listas (caixas, clientes, papéis…) o celular empilha tudo em cartões, mas os valores apareciam sem nome — dava pra ler "824×1212 · 290×285×530 · 656.1g" sem saber o que era cada um. Agora cada dado vem com o nome da coluna em cima, e os campos vazios somem em vez de virar um monte de "—".
📝 A janela de pedido agora ocupa a tela toda. Tinha um erro no HTML que deixava os botões Excluir / Cancelar / Salvar do lado de fora da janela — no celular eles flutuavam soltos no escuro. Corrigido: a janela sobe de baixo, do tamanho da tela, e o Salvar fica na parte de baixo, onde o polegar alcança.
📋 O aviso de parcial sem entrega remarcada agora aparece também no PCP (aba Carteira, embaixo dos cartões). Antes só no Dashboard — e é no PCP que você mexe em data. Mesmo aviso, mesmo botão de remarcar, nos dois lugares ao mesmo tempo.
⚠️ Pedido parcial não fica mais "atrasado" à toa. Quando um pedido é parcial e a decisão é continuar o mesmo número, o sistema guardava quanto falta — mas ninguém remarcava a entrega. No dia seguinte ele aparecia como atrasado sem estar, e não era erro de ninguém: nem o botão do PCP nem o caminho do operador pedem data nova (e o operador nem decide data de cliente).
📅 Agora aparece um aviso na lista de pedidos com quem está nessa situação: quanto falta, qual a data antiga, e se ele nunca foi remarcado. O botão Remarcar entrega abre o pedido já pedindo a data nova — que é o caminho que sempre soube fazer isso do jeito certo.
🧾 Os dois da TANGARA que estavam assim (23610 e 23611, faltando 8.843 e 5.062 cx) foram remarcados pra 31/07. Os atrasados caíram de 17 pra 15.
A parte já produzida continua no estoque e carregável; o que falta continua na programação. Nada de status foi trocado — trocar status de pedido com produção é o que fez o 23393 perder paletes.
🔮 O "Pergunte" virou um campo de busca no meio da tela. Em vez de abrir uma janelinha com título e botões, agora abre um campo só, no centro, com o sistema desfocado atrás — igual ao Spotlight do Mac.
⌨️ Atalho ⌘K (ou Ctrl+K no Windows) abre de qualquer aba, sem caçar o botão. Enter pergunta, Shift+Enter pula linha, Esc fecha.
🌈 Ele mostra que está trabalhando. O anel colorido em volta do campo gira devagar; enquanto a IA pesquisa ele acelera e as beiradas da tela acendem. Some a dúvida de "travou ou está pensando?".
📐 O campo cresce sozinho se a pergunta for longa, e a resposta ganhou mais altura de leitura — a tabela da ficha de produção agora cabe.
Só o visual mudou; a consulta é a mesma da v2.37.119.
🤖 O "Pergunte ao sistema" agora PESQUISA, não adivinha. Antes ele recebia um resumo fixo (só a lista de pedidos, com 6 informações cada) e tinha que se virar com aquilo. Por isso sabia dizer "17 pedidos atrasados" mas não sabia dizer quais, e sobre produção respondia "não tenho essa informação".
🔎 Ele consulta o banco, quantas vezes precisar. Ganhou 6 consultas de leitura: contadores gerais, lista de pedidos com filtro (atrasados, cliente, status, período), detalhe de um pedido com todos os apontamentos, ficha de produção do dia (máquina, operador, caixas, paletes, ajuste, paradas, cx/h real x cadastro), totais por dia/cliente/operador/máquina e a lista de nomes reais (pra achar a máquina mesmo se você escrever o apelido).
📅 Entende "dia 24", "ontem", "essa semana" e sabe que atrasado não é status — é entrega vencida sem ter sido entregue, a mesma conta do painel.
👀 Mostra o que foi olhar. No pé da resposta aparece quais consultas ele fez, pra você poder conferir. E a resposta agora sai formatada — antes vinham os asteriscos crus na tela.
🔒 Continua só leitura: ele não muda, não apaga e não cria nada.
Obs.: precisa do restart da API no servidor pra valer.
⚡ O sistema abre muito mais rápido. Antes, cada abertura baixava tudo de novo — mais de 2,5 MB de código, toda vez, no wifi da fábrica. Agora só baixa o que mudou de versão. A primeira abertura depois de uma atualização baixa uma vez; da segunda em diante é instantâneo.
🚀 A carteira carrega numa consulta só. O servidor fazia uma consulta por pedido (com 400 pedidos, 401 idas ao banco em cada carregamento, para cada aparelho aberto). Agora é uma. Some a demora do "carregando pedidos" e a fila quando vários PCs usam junto.
🕐 "Num PC aparece e no outro não" — resolvido. O sistema comparava o relógio do PC com o relógio do servidor pra decidir se buscava novidade. PC alguns segundos adiantado parava de receber as mudanças dos outros até dar F5. Agora usa só a hora do servidor.
🛡️ App não fica mais preso numa tela de erro. Se o servidor respondesse errado num momento ruim (durante uma atualização, por exemplo), essa resposta era guardada e reaparecia depois, offline, no lugar do app. Agora só resposta boa é guardada.
🔑 A senha do operador saiu de texto puro. O PIN de 4 dígitos era guardado e enviado aberto: aparecia pra qualquer navegador que abrisse o sistema e vinha inteiro num backup do banco. Agora o banco guarda só um código embaralhado e a conferência é feita no próprio aparelho — o login do operador continua funcionando sem internet, exatamente como antes.
👤 No cadastro, o campo da senha vem vazio. Vazio mantém a senha atual (dá pra corrigir nome ou máquina sem redigitar o PIN); 4 dígitos trocam a senha. Antes o ✏️ mostrava a senha real na tela.
✅ Ninguém precisa recadastrar nada — os operadores continuam entrando com o mesmo PIN, a troca é automática.
Obs.: PIN de 4 dígitos tem 10.000 combinações; isso protege contra quem apenas OLHA (backup, painel do navegador), não contra ataque dedicado. Proteção maior pediria PIN mais longo.
⚖️ Caixa "sem peso" que estava cadastrada agora é achada. Quando o pedido traz o nome do cliente dentro do código ("KININO 22") e o cadastro tem só o número ("CX 22"), o sistema não achava a caixa — e o Relatório de Produção acusava "cadastro incompleto" mesmo com a caixa cadastrada e pesada. Agora ele ignora esse prefixo e casa. 70.344 cx voltaram a ter peso (Kinino 22, 42, 07, 06 e 25).
O resto do código continua tendo que bater inteiro e a caixa é sempre do mesmo cliente — nunca pega caixa de outro.
🔑 A senha do operador saiu de texto puro. O PIN de 4 dígitos era guardado e enviado aberto: aparecia pra qualquer navegador que abrisse o sistema e vinha inteiro num backup do banco. Agora o banco guarda só um código embaralhado e a conferência é feita no próprio aparelho — o login continua funcionando sem internet, como antes.
👤 No cadastro de operador, o campo da senha vem vazio. Deixar vazio mantém a senha atual (dá pra corrigir nome ou máquina sem redigitar o PIN); digitar 4 dígitos troca a senha. Antes o ✏️ mostrava a senha real na tela.
✅ Ninguém precisa recadastrar nada. Os operadores que já existem continuam entrando com o mesmo PIN — a troca é automática e sem interrupção.
📊 Fim do registro duplicado que inflava o estoque. Ao importar a produção do operador, o sistema comparava data+horário+quantidade em vez do número do registro. Bastava a quantidade chegar como texto, ou o horário de fim variar 1 segundo, pra entrar duas vezes — e o Estoque PA subia sozinho. Pior: dois registros legítimos com mesma quantidade e horário (turnos/operadores diferentes) eram fundidos num só, e aí a produção desaparecia. Agora casa pelo número do registro.
📄 Nota de papel não entra duas vezes. NF cujo XML vem sem a chave de acesso podia ser importada infinitas vezes, e cada import somava no estoque (sem jeito de estornar). Agora toda nota tem identificação própria e a segunda tentativa é recusada.
💰 Valor com vírgula não zera mais. Valor/peso escritos no padrão brasileiro (1.234,56) entravam como número inválido e contaminavam a soma de todas as notas. Agora são lidos certo.
🔁 Fim do "programei e voltou". Quando o operador pedia pra reprogramar, o sistema aplicava mas nunca marcava o pedido como resolvido. Depois que você lançava a chapa, qualquer F5 fazia o pedido voltar pra reprogramado e perder a chapa. Corrigido.
🛡️ Trava anti-apagão mais forte. Se o sistema não conseguir confirmar com o servidor, ele agora não salva em vez de arriscar apagar (antes uma oscilação de internet liberava o apagamento) e avisa na tela.
📦 Expedição: bipagem não se perde mais. Ao finalizar o caminhão sem internet, o app guarda as bipagens e avisa pra não fechar — antes elas eram apagadas do aparelho e sumiam.
🧰 Almoxarifado. "Confirmar saída" trava contra toque duplo (não baixa o estoque em dobro) e item que falhou na entrada fica no carrinho em vez de ser jogado fora.
🔒 Segurança e números. Nome de insumo com código dentro não executa mais na tela de Custos; app de Qualidade ganhou a mesma proteção; e o Relatório e o "Pergunte ao sistema" pararam de somar apontamento arquivado (o número pode diminuir — agora bate com a produção).
🗓️ Cronograma virou relatório fiel. As barras agora ancoram no horário real do apontamento do operador; o que foi programado e não rodou aparece marcado (não some, volta no próximo dia útil); o turno da noite fica no lugar certo; o cronograma respeita o turno (sem hora que não existe); e fim de semana é folga.
📋 Nova tela: Ficha do Operador (aba Análises). Relatório diário por máquina com só o que foi feito de verdade: por pedido, início/ajuste/produção/perda/fim, paradas, ocorrências; + % de eficiência e comparativo cadastro × real (ex: era 3.000/h, rodou 2.000/h). Filtro por dia/semana. Cronograma e ficha são espelho do que aconteceu.
🎨 Cores virou "Cores e Acabamentos". O mesmo cadastro agora guarda as tintas (com R$/kg e gramatura) e os acabamentos — BOPP, verniz, hot stamp, laminação — com o preço por m². Tem filtro pra ver só um tipo e dois botões: + Nova Tinta e + Novo Acabamento.
💰 Acabamento entra no custo. O sistema mede a área da camada na arte, multiplica pelo R$/m² cadastrado e soma no orçamento — junto com a tinta. Na ficha da caixa cada acabamento também escolhe qual é, igual as tintas.
Se a camada da arte não bater com nenhum cadastro, ele avisa em vez de chutar preço.
💰 Arte direto no orçamento. Agora dá pra jogar o .ai ou .pdf da arte dentro do orçamento — mesmo pra caixa que ainda não está cadastrada. Ele mede as tintas na hora e já entra no preço. Se a caixa já tem ficha no cadastro, continua puxando de lá sozinho.
✨ Acabamento virou categoria própria. Camadas de BOPP, verniz, hot stamp, laminação, relevo, UV e afins são reconhecidas e medidas, mas não entram na conta de tinta — são outro material. Cada linha agora tem 3 opções: 🎨 tinta · ✨ acabamento · 🔧 técnico — dá pra corrigir na mão se vier errado.
⚠️ Aviso de camada vazia. Se a arte tiver uma camada criada mas sem nada desenhado, o sistema avisa em vez de deixar passar em branco.
📐 Arte do Illustrator (.ai) lida pelas CAMADAS. Agora dá pra jogar o arquivo .ai direto na seção 6.6 do cadastro da caixa. Quando o arquivo tem camadas nomeadas (ex.: "vermelho", "amarelo", "verde"), o sistema mede cada camada separada e usa o nome da camada como nome da tinta — em vez de adivinhar pela cor do desenho. Isso deixa a medida exata (a soma das camadas bate com o total) e o vínculo com o cadastro de Cores é automático pelo nome. Camadas de corte, vinco, faca, cotas e afins são reconhecidas pelo nome e descartadas sozinhas.
Arquivos sem camadas continuam sendo lidos pelas cores, como antes.
🎨 A tinta agora sai do cadastro de Cores. No Cadastro → Cores cada tinta ganhou preço (R$/kg) e um botão "Mandar pro Almoxarifado" — você cadastra a tinta uma vez, com o preço, e ela vira item de estoque. Na ficha de tinta da caixa (seção 6.6), cada cor lida do PDF agora vincula numa cor cadastrada — e ele já sugere sozinho a mais parecida. Com isso o orçamento puxa o preço certo e a tela "precisa comprar?" acha o estoque pelo vínculo (não mais "chutando" por nome parecido). A seção 6.6 também passou a aceitar arquivo .ai do Illustrator.
🐛 Corrigido: a leitura do estoque de tinta não funcionava no painel central (voltava sempre vazia, sem avisar) — o orçamento acabava usando o preço padrão e a tela dizia "sem estoque". Agora lê certo, e se falhar avisa na tela.
🎨 Consumo de tinta — novo módulo. No cadastro da caixa (seção 6.6) você joga o PDF da arte e clica em Analisar tinta: o sistema mede a área de cada cor, descarta sozinho as marcas de corte/vinco/cotas do clichê e salva a ficha. No Almoxarifado a tinta ganha cor e R$/kg. Nova tela "🎨 Tinta — precisa comprar?" (em Análises) cruza a carteira com o estoque e mostra o que falta comprar — inclusive nos próximos 2/10/15/20 dias. E o orçamento passa a somar o custo da tinta (R$/kg × gramas por caixa).
📋 Orçamento puxa a caixa do cadastro. Ao escolher uma caixa já cadastrada do cliente no campo Referência, o orçamento agora preenche sozinho as medidas (C×L×A) e o estilo (corte-e-vinco ou maleta pela onda). E logo abaixo do R$/kg aparece uma linha só de referência com o último preço, o R$/kg e o peso do cadastro daquela caixa — pra comparar na hora, sem mexer no cálculo.
🔢 "fez" conta só a etapa final. Num pedido de duas etapas (ex.: Corte/Vinco → Coladeira), o "fez" da Carteira somava as DUAS etapas por engano (corte 6.428 + coladeira 12.157 = 18.585). Agora conta só o que virou caixa pronta (a etapa final) — bate com a barra de progresso e com o estoque.
v2.37.105 paletes fora
23/07/2026
📐 Paletes fora do padrão (Expedição). Nova tela na aba Expedição que lista os pedidos ativos cujas caixas estão cadastradas com "Palete fora do padrão" — pra pedir ao setor de paletes fabricar. Mostra cliente, caixa, quantidade, medida do palete a fazer, quantos paletes e o prazo. Botões pra imprimir/salvar PDF e copiar o texto pro WhatsApp do responsável.
📦 Produzido = paletes confirmados. O número que conta como produzido/concluído (e vai pro estoque) passa a ser a soma dos paletes confirmados — o físico real, o que o operador aponta. A contagem da máquina que passar disso não infla mais o estoque. O espelho (+1 no papel) fica só na etiqueta. Vale pros próximos pedidos finalizados. (Pedidos já finalizados mantêm o número antigo até corrigir.)
🔢 Numeração em TODO pedido. Os pedidos que entraram depois (fora da "Ordem de Produção") também ganham número, no fim da fila — antes ficavam sem. O mesmo número aparece no cronograma e no app do operador.
🗓️ Cronograma renovado (planta nova, fases 1–8). Pedido finalizado sai da máquina na hora — acaba a etapa que ficava "presa" rodando eterna — e o que roda de verdade sempre aparece. Numeração fixa 1º/2º/3º… no cronograma e no app do operador (concluir não renumera). Card ao vivo com operador, início/fim real, duração, velocidade e o log (ajuste · produção · parada), onde manutenção não penaliza e ajuste conta. % e paletes prontos no acabamento + barra geral do turno. Aviso ao pegar fora da ordem (⚡ antecipado). Acabamento herda a ordem do corte. Velocidade por média real (opcional, desligada por padrão).
📈 Nova tela "Relatório de Produção" (aba Análises). Quantas toneladas e quanto em R$ a fábrica fez — hoje, esta semana e este mês — com Produzido × Faturado lado a lado, ticket médio de peso e valor por dia, e o destaque do cliente que mais fez em cada período.
📋 Fechamento do mês com seletor de mês: total produzido/faturado, semanas do mês (com destaque de cada semana), dia a dia, e o top clientes por peso e por valor.
⚖️ Tonelada bate com o Estoque: conta só a etapa final (caixa pronta), sem somar impressora + coladeira duas vezes. Onde a caixa não está vinculada no cadastro, mostra o aviso "⚠ cx sem peso" pra você saber o quanto ainda falta cadastrar.
🔄 Reiniciar volta o pedido pra "A Programar" de verdade. Tinha um bug: ao clicar em Reiniciar, o servidor deixava o pedido com material + chapa e o operador pegava de novo → voltava pra "EM PRODUÇÃO". Agora o Reiniciar zera o status e a chapa nos dois lados (servidor + tela) — o pedido fica em "A Programar" e não volta sozinho.
🗑️ Botão "Resetar paletes (tirar do estoque)". No histórico do pedido e na tela Estoque PA — tira TODOS os paletes de um pedido do estoque de vez, anulando a produção da etapa final no servidor (some nos dois PCs, não volta no sync). A Slotter e as etapas do meio não são tocadas.
📦 Estoque não infla mais quando a etapa final é zerada. Antes, ao reiniciar/resetar a grampeadeira (ou coladeira), a conta de "caixa pronta" contava a Slotter por engano e o estoque subia em vez de zerar (chegou a divergir entre dois PCs — Mac × Windows). Agora caixa pronta é só a etapa final da rota: etapa final zerada = 0.
🖱️ Scroll do PCP. A rodinha do mouse voltou a rolar a Carteira (a tabela larga estava "prendendo" a rolagem — dava pra rolar só pela barra de fora).
👻 Reiniciar limpa o "fantasma" da decisão parcial. Um pedido reiniciado não aparece mais na tela "Decisão de Produção Parcial" com um número produzido que não existe mais.
v2.37.99 etiqueta medidas
22/07/2026
🏷️ Etiqueta mostra as MEDIDAS INTERNAS da caixa (no lugar de "Cliente"). Era um bug: o código lia os campos errados das medidas, então a etiqueta sempre caía no "Cliente.:". Agora, quando a caixa tem as medidas cadastradas (C interno / L interno / A interno), a etiqueta mostra "Medidas internas.: C×L×A" (sem medida, continua mostrando o cliente).
🚚 "Carregado por" no romaneio do PLANO de carga. No romaneio feito a partir do plano, o campo "Carregado por (empilhadeirista)" agora já vem preenchido com quem bipou os paletes (o login do app Expedição) — antes só o romaneio da carga sem plano preenchia; no do plano ficava em branco.
v2.37.98 etiqueta lotes
22/07/2026
🏷️ "Total do PEDIDO (todos os lotes)" só aparece na etiqueta quando o pedido FINALIZA. Antes, ao reimprimir um lote parcial (ex.: Lote 2), a etiqueta já mostrava "Total do PEDIDO (todos os lotes)" mesmo o pedido ainda não tendo acabado (faltava liberar mais caixas) — enganava. Agora, no lote parcial sai só o "Total do LOTE"; o "Total do PEDIDO (todos os lotes)" só aparece quando você finaliza (produziu a quantidade do pedido) — aí sim é o total de verdade.
v2.37.97 anti-duplicação
22/07/2026
🛡️ Fim das duplicações de registro. Dois bugs que criavam registro repetido (e dobravam o estoque) foram atacados na raiz: (1) corrigir palete/quantidade criava uma CÓPIA em vez de mudar (e às vezes o número voltava sozinho) — o servidor agora manda o id certo pro app, então a correção acha o registro e MODIFICA, e o sync do pedido virou "só-adiciona" (não sobrescreve mais); (2) finalizar 2× a mesma produção (com delay de rede, ex.: um lançamento 07:59 e outro 08:00) criava 2 registros — agora o app checa se essa produção já foi finalizada e não lança de novo (reabertura e lotes continuam liberados).
🔧 Depende do Luan subir o servidor (a parte do bug 1 é no api/). A parte 2 (finalizar) sobe no push.
v2.37.96 botão salvar
21/07/2026
🖨️ Corrigir palete no PCP mais claro. O botão que salva cada palete agora é "✔️ SALVAR" escrito (antes era só um lápis pequeno, fácil de confundir com o "Salvar registro" verde do rodapé — dava pra clicar no errado e a correção não gravava). Uma dica no painel explica que é esse botão, e agora também dá pra apertar Enter no campo pra salvar aquele palete.
v2.37.95 palete+estoque
21/07/2026
🏷️ Corrigir palete direto no PCP + estoque automático. No histórico do pedido, do lado do "Imprimir etiquetas", agora tem "✏️ Corrigir palete" — corrige a quantidade de um palete sem precisar do celular do operador. Reimprime a etiqueta certa (o QR não muda, a bipagem continua) e o Estoque PA atualiza sozinho.
🖨️ Etiqueta nunca sai em branco. O último palete agora sempre imprime o número (antes saía "EM ABERTO — ANOTAR" quando você imprimia pelo "prontos e continuar"). Se a quantidade estiver errada, corrige na tela (operador ou PCP) e reimprime — o papel sempre sai com o número certo.
🔄 Estoque bate entre os computadores. Cada PC agora recalcula o próprio estoque a partir da carteira (que já é igual em todos) — antes um computador podia sobrescrever a correção do outro e o número voltava. Também: o "×" (arquivar) só baixa o estoque depois de confirmar que salvou no servidor, e caixa de pedido 100% arquivado some do estoque (acabou a "caixa fantasma").
🎯 Card do operador mostra a ARTE. Quando dois pedidos têm o mesmo número (ARTE 1 e ARTE 2), o card do operador mostra a ARTE em destaque pra não confundir uma com a outra.
v2.37.94 espelho+estoque
21/07/2026
🏷️ O espelho agora entra na conta em TODO lugar — "confirmadas" bate com o total. Antes o "X cx confirmadas" (embaixo dos paletes, no operador e no PCP) somava os paletes sem o espelho e ficava diferente do total concluído / do estoque (que já vinham com o espelho) — ex.: 4 paletes davam 7.707 confirmadas mas 7.711 no estoque. Agora cada palete conta caixa + espelho (ex.: 2.100 + 1 = 2.101; o último 300 + 1 = 301) e a soma fica igual no confirmadas, no total, no estoque e na etiqueta. O campo de quantidade produzida também já sai com o espelho — o operador não precisa mais somar o +1 na mão.
🔧 Corrigir palete no concluído — Fase 2 (servidor). Quando o operador corrige um palete num pedido já concluído, agora a correção também atualiza o número daquele palete no PCP (na reimpressão e no Estoque PA), não só o total. E veio a trava de verdade: se o palete já foi bipado numa carga, o sistema recusa a correção (aí o ajuste é na Expedição). Depende do Luan subir o servidor — a parte do operador já funciona sozinha.
🗄️ Conserto do estoque que "duplicou" + arquivar registro que gruda. Quando a MESMA produção era gravada em 2 registros, o Estoque PA somava os dois (ex.: 5 paletes viravam 10, o dobro de caixas). Agora: (1) o × no histórico do pedido arquiva de verdade — antes ele só sumia da sua tela e voltava no próximo sync; agora fica guardado (riscado, marcado ARQUIVADO) e não volta; (2) o registro arquivado sai da conta e do estoque na hora; (3) consertei o "Informe a data" que travava quando você só mexia no histórico. Depende do Luan subir o servidor (a rota de arquivar).
v2.37.93 operador
21/07/2026
🏷️ Reimprimir e corrigir palete no pedido JÁ concluído (app do operador). Na aba Concluídos, ao abrir um pedido finalizado, agora tem uma seção "Etiquetas dos paletes": um botão 🖨️ Reimprimir por lote, e a lista dos paletes com um ✏️ pra corrigir a quantidade de um palete e reimprimir a etiqueta certa. O total do pedido ajusta pela diferença e sobe pro PCP. Só aparece nas máquinas de Fechamento (Coladeira/Grampeadeira, pelo cadastro de Máquinas), do próprio aparelho, dentro de 24h. O QR não muda com a correção, então a bipagem segue certa (aviso na tela: se o palete já foi bipado numa carga, a carga precisa de ajuste na Expedição).
🔧 Falta a Fase 2 (servidor, com o Luan): pra a reimpressão pelo PCP daquele lote e o detalhe por palete no Estoque PA também refletirem o palete corrigido, e pra travar de vez a correção de um palete já bipado. Por enquanto, a reimpressão pelo operador já sai certa e o total do pedido fecha.
v2.37.92 espelho
21/07/2026
🔧 Conserto: o espelho voltou pro número de cada palete na etiqueta do PCP. Na v2.37.91 eu tinha deixado o espelho só no total do lote e tirado do número de cada palete na etiqueta do PCP — aí a quantidade de cada palete saía sem o espelho, diferente da etiqueta do operador. Agora a Quantidade no Palet. volta a sair com o espelho (ex.: 1001 + 1 = 1002), com a notinha "+1 espelho", igual nas duas etiquetas. O QR continua com o número puro, então a bipagem não muda.
v2.37.91 etiqueta
21/07/2026
🏷️ Etiqueta do palete mais clara + os espelhos entram na conta. Aqueles dois números que confundiam agora têm nome: "Total do LOTE (com espelhos)" (a soma dos paletes daquele lote, já somando a caixa-espelho de cada um) e "Total do PEDIDO — todos os lotes" (o acumulado). O espelho entra só no total — o número de cada palete e o QR não mudam (a bipagem continua certa). E na hora de finalizar, se o operador digitar um número que não bate com os paletes (ex.: copiou o contador da slotter), o sistema avisa.
🖨️ Imprimir paletes prontos e continuar (PCP e operador). Agora dá pra reimprimir qualquer lote já feito: no card do pedido (com vários lotes) abre uma lista "Lote 1, Lote 2…" com um botão Reimprimir em cada. E o operador ganhou o botão "🖨️ Imprimir prontos e continuar" — libera e imprime os paletes que já confirmou sem fechar o pedido, seguindo a produção. O QR já sai com o número do lote, então não duplica na bipagem (corrigimos de vez a duplicação que existia em pedido de vários lotes).
🔄 Vista 3D do baú gira com o dedo (app da Expedição). Na tela do empilhadeirista, a visão 3D do caminhão carregado agora roda arrastando o dedo (ou o mouse) — dá pra ver o baú de todos os lados. Um botão 🔄 endireita a vista quando quiser. Parado, fica igualzinho ao de antes; as cores de bipado/pronto/em-produção não mudam.
v2.37.89 pilha
20/07/2026
✋ Ajuste manual da pilha na planta de carga. Agora dá pra clicar numa pilha e mandar como ela fica: (1) inverter base/topo — escolher qual caixa vai embaixo (o automático põe a maior, mas às vezes a mais firme é a menor, tipo a 24x8 embaixo da 18x16); e (2) puxar um palete que ficou pra trás e empilhar em cima na mão, com o sistema conferindo a altura na hora. O palete sai de verdade do "ficou pra trás" e vira carga bipável — sem contagem dobrada.
🛡️ Com trava de segurança. Altura é o único bloqueio duro. Empilhar em cima de outro cliente ou de um palete parcial pede confirmação. Dá pra desfazer (o palete volta pra trás) e o ajuste fica salvo com o plano e sobrevive ao recálculo. Sem nenhum ajuste manual, o plano sai idêntico ao de antes.
v2.37.87 planta
20/07/2026
🔤 Nomes das pilhas na planta de cima não se sobrepõem mais. Quando uma coluna tem dois paletes DIFERENTES empilhados, os nomes ficavam um por cima do outro, ilegíveis. Agora o palete de cima aparece escrito no topo da célula (com ▲) e o de baixo no rodapé, bem separados. Coluna de um modelo só (dois paletes iguais) continua mostrando um nome centralizado, como já estava certo.
v2.37.86 pareamento
20/07/2026
🧩 Pareamento inteligente das pilhas — o maior sempre embaixo. Antes o sistema empilhava de forma gulosa: cada modelo se dobrava sozinho, e sobrava o palete maior POR CIMA de um menor (aquela sobra de 4cm que você marcou). Agora ele monta as colunas de cada cliente escolhendo o melhor par: o palete de base maior fica embaixo e o menor encaixa dentro, sem sobrar pra fora. No exemplo POWERDENT, cada TIPO 07 vira base com um TIPO 14 encaixado em cima — mais estável e mais consolidado, sem overhang.
🛡️ Com rede de segurança e sem quebrar nada. Se o pareamento por acaso couber menos carga que o jeito antigo, o sistema volta pro antigo automaticamente — nunca carrega menos que antes. O que já funcionava fica idêntico: empilhar desligado, cliente de um modelo só, e a bipagem no app não mudam. O palete pronto tende a ficar de base e o em produção por cima. ⚠️ Os desenhos de clientes com vários modelos vão aparecer diferentes (melhor arrumados) — é esperado.
v2.37.85 config
20/07/2026
⚙️ Folgas do empilhamento agora são configuráveis. No Planejamento de Carga, ao lado de "Empilhar paletes", tem o link "⚙️ ajustar folgas" que abre uma tela pra você mexer nos três limites (em centímetros): altura extra da pilha (quanto pode passar do baú), sobra pra fora (quanto o de cima pode passar da borda) e menor que a base (quanto o de cima pode ser menor). Salva e sincroniza entre os aparelhos; tem "restaurar padrão" (10 · 15 · 30 cm). Antes só dava pra mudar no código.
v2.37.84 empilhamento
20/07/2026
📦 Palete um pouco maior agora empilha (até 15cm de sobra pra fora). O TIPO 07 não subia no TIPO 14 mesmo sendo o mesmo cliente e cabendo na altura — porque o TIPO 07 é ~7cm maior na base (1068×1284 contra 1000×1200), e a regra antiga não deixava sobrar nada pra fora da borda. Agora o palete de cima pode sobrar até 15cm por lado — cobre o caso do TIPO 07 (~4cm de sobra) e outros paletes quase do mesmo tamanho. O de cima continua não podendo ser pequeno demais (até 30cm menor, pra não afundar no meio das caixas), e paletes muito diferentes continuam barrados.
v2.37.83 empilhamento
20/07/2026
📦 Empilhamento agora é PROATIVO — não espera o chão encher. Antes, palete cheio só empilhava em cima de outro quando o caminhão lotava; com chão sobrando, ficava tudo lado a lado (ex.: o TIPO 07 do POWERDENT não subia na sobra do TIPO 14, mesmo cabendo). Agora qualquer palete tenta subir numa coluna do mesmo cliente que tenha folga, antes de ocupar chão — consolida a carga e libera espaço. As regras de segurança continuam: mesmo cliente, cabe na altura do baú (+10cm), e o de cima encaixa dentro do de baixo (até 300mm menor).
🔽 Quem é pronto vira base, quem está em produção vai por cima — naturalmente, porque o pronto (do estoque) é posicionado primeiro. Assim o palete que já existe fica embaixo e o que ainda vai ser feito sobe. Se ver alguma pilha que não faz sentido, me avisa que ajusto.
🔴 Trocar de caminhão apagava os clientes da entrega — corrigido. Ao editar um plano e trocar pra um caminhão que não tem viagem na escala, o sistema zerava a lista de clientes e a carga sumia. Agora trocar de caminhão só reencaixa a MESMA carga no baú novo — os clientes ficam. A escala só é puxada automaticamente quando a entrega está vazia (conveniência do plano novo). A carga é do pedido, não do caminhão: dá pra trocar de caminhão pra ver se cabe melhor, sem perder nada.
v2.37.81 plano de carga
20/07/2026
🔤 Nome da caixa não vaza mais do palete na planta de carga. Na vista de cima, o código comprido (ex.: "TIPO 14 SEM IMPRESSAO", "CX 220016 MILI BEAUTY 18X16") passava por cima do palete do lado. Agora ele encolhe a fonte pra caber, corta com "…" quando o palete é muito estreito, e fica travado dentro da borda — nunca invade o vizinho. O nome completo continua na lista de clientes do lado.
✏️ Atalho pra editar o caminhão. Ao lado das medidas do baú, no Planejamento de Carga, agora tem o link "✏️ editar medidas" que abre direto o cadastro do caminhão — sem ter que caçar em Cadastros. (Pra trocar de caminhão continua sendo o seletor de cima.)
v2.37.80 3D 2 lados
20/07/2026
👀 Isométrica do Plano de Carga agora mostra os DOIS lados do caminhão. Na vista 3D, os paletes da frente escondiam os de trás — um lado do baú ficava oculto. Agora aparecem duas vistas lado a lado ("um lado" e "outro lado"): a segunda é o baú girado 180°, então o lado que ficava escondido vira a frente. Nada mais fica atrás. É só desenho — não muda o cálculo da carga nem a bipagem. (No app do empilhadeirista, que é celular, segue uma vista só; se precisar, dá pra pôr um botão "girar" depois.)
v2.37.79 empilhamento
20/07/2026
📦 Empilhamento CRUZADO no Plano de Carga — palete pequeno em cima do grande. Antes o sistema só empilhava palete idêntico (mesmo modelo). O palete parcial (o quebrado, mais baixo) ficava sozinho ocupando um lugar inteiro no chão do caminhão com um monte de espaço vazio em cima. Agora ele sobe em cima de um palete cheio do mesmo cliente, liberando chão pra caber mais carga. No exemplo da BLUE SEA, uma carga que ocupava 4 lugares no piso passou a ocupar 2.
🛡️ Com as regras de segurança que você definiu: o de cima tem que caber dentro do de baixo (nada sobra pra fora da borda), fica centralizado e no máximo 300mm menor por lado; a pilha pode chegar a 2.500mm (baú de 2.400 + os 100mm de folga). Só o mesmo cliente empilha junto (pra não soterrar a carga de outra entrega), e um palete parcial nunca vira base (a camada de cima dele pode ser incompleta). Palete sozinho mais alto que o baú continua barrado.
🎨 Desenho e app. A planta 2D marca o empilhado com ▲ e a isométrica mostra o palete menor pousado em cima. No app da Expedição vale o mesmo — e a bipagem não mudou: cada palete continua com sua etiqueta própria, então o empilhadeirista bipa igual. Tudo atrás do mesmo botão "Empilhar paletes"; desligado, o plano fica idêntico ao de antes.
🔴 Plano de Carga contava só o que faltava do Slotter, não a carga inteira (POWERDENT). O pedido TIPO 07 tinha 8.000 cx e o Slotter já tinha cortado 7.763, mas o plano mostrava só 237 cx / 1 palete. E a caixa TIPO 14 do mesmo cliente sumia. Causa: o plano calculava "em produção" como qtd − produzido, e o "produzido" contava o Slotter (a 1ª máquina, o corte). Só que caixa cortada no Slotter ainda vai pra Coladeira — não é caixa pronta e não está no estoque. Então quando o Slotter cortava quase tudo, sobrava um resto minúsculo; e quando cortava a quantidade toda (ou mais), o modelo zerava e desaparecia do plano.
✅ Agora a previsão é a carga inteira do pedido. Enquanto nada está finalizado (pronto no estoque PA), o plano mostra o pedido inteiro como "em produção" — desconta só o que já virou pronto de verdade, não o corte intermediário. TIPO 07 passou de "237 cx / 1 palete" pra 8.000 cx / 5 paletes, e a TIPO 14 voltou a aparecer com 5.000 cx / 3 paletes. Assim o PCP enxerga a carga real que está vindo, mesmo antes de finalizar.
🔧 Caixa vinculada e certa ainda aparecia "sem paletização" no carregamento (BLUE SEA). A correção da v2.37.72 (prefixo CX opcional) valia só pros PEDIDOS. Mas o que está PRONTO no Estoque PA passava por outro casamento — um mais antigo, exato e sensível a maiúscula — que não ignorava o prefixo. Então a caixa 220016 MILI BEAUTY 18X16 com 7.833 cx prontas não achava o cadastro CX 220016 MILI BEAUTY 18X16 e caía como "sem paletização", mesmo com a caixa cadastrada e completa. Agora o Estoque PA usa o mesmo casamento dos pedidos (com o prefixo opcional e a trava por cliente — nunca pega caixa de outro cliente).
🔴 Palete contado em DOBRO quando o pedido atravessa o turno (bug antigo, corrigido). Nada marcava quais paletes já tinham entrado num registro. O fim de turno zera a quantidade parcial mas não mexe nos paletes, e o operador seguinte adota a lista inteira com todos ainda marcados como confirmados. Resultado, num pedido de 10 paletes: o turno 1 gravava [1..5] e o finalizar gravava [1..5, 6..10] — os cinco primeiros de novo. O Estoque PA somava os dois registros e enxergava 15 paletes onde existiam 10.
🏷️ E gerava etiqueta duplicada. Como a plaquinha numera pela posição na lista impressa, os paletes 1 a 5 ganhavam uma segunda etiqueta no lote 2, com QR diferente — o mesmo palete físico ficava bipável duas vezes na Expedição, inflando a carga. Agora cada palete é carimbado com o número do lote assim que entra num registro, e os registros seguintes só levam os que ainda não foram. O carimbo é feito depois da gravação: se o registro não salvar, ninguém fica carimbado e o palete entra no próximo — nunca some.
🔢 O lote agora é gravado, não deduzido. Antes o número do lote era a posição do registro na lista — anular ou deduplicar um registro renumerava todas as etiquetas já coladas. Agora vem gravado no registro e no próprio palete; a posição ficou só como reserva pra registro antigo (e passou a ignorar registro anulado).
📅 App da Expedição: filtro por dia na lista de planos. A lista mostrava todos os planos em aberto de uma vez — plano de terça aparecia junto com o de hoje e o empilhadeirista tinha que adivinhar qual era o dele. Agora abre no Hoje por padrão, com o botão Todos do lado (que mostra a contagem de cada um: "📅 Hoje (2)" · "Todos (3)").
🛡️ E o filtro nunca esconde serviço. Se não houver plano de hoje mas existir um de outro dia em aberto, a tela não diz "nenhum plano liberado" (que faria ele achar que não tem trabalho) — diz "Nenhum plano de hoje · mas tem N plano(s) em aberto de outro dia" e aponta o botão. A barra de filtro só aparece quando existe plano de outro dia; sem isso, ela nem ocupa espaço. O contador do menu continua somando todos os planos em aberto.
🎯 O aviso mandava fazer a coisa errada — corrigido. A versão anterior dizia "sem paletização — cadastrar a caixa" pra tudo. Só que são dois problemas diferentes, e num deles a caixa já está cadastrada e completa: a KININO tem 15 caixas cadastradas com paletização (CX 01, CX 03, CX 05…) — o que não bate é o código do pedido, que diz KININO 44 e não existe. Mandar "cadastrar a caixa" faria você perder tempo mexendo num cadastro que já estava certo.
🔀 Agora cada caso diz o conserto certo:
• "N códigos sem caixa no cadastro — vincular ao pedido": a caixa existe, o código do pedido é que aponta pro vazio (KININO, Granja Hattori). Conserto = vincular o pedido à caixa certa.
• "N caixas sem paletização — preencher no cadastro": o código bate, achou a caixa, mas ela está sem paletização (Tchetto, TANGARA). Conserto = preencher a paletização daquela caixa.
No card do cliente vale o mesmo: em vez do genérico "caixa não cadastrada", aparece "código sem caixa no cadastro" ou "caixa sem paletização".
🔎 O aviso de caixa sem paletização agora diz QUAL caixa é. Antes aparecia só o total ("30.000 cx sem paletização") e você tinha que caçar qual modelo estava faltando. Agora o seletor lista caixa por caixa, com a quantidade de cada uma, ordenado da maior pra menor — resolvendo a de cima você mata o maior buraco primeiro. Ex.: ⚠️ 3 caixas sem paletização (30.000 cx): • KININO 53 — 12.000 cx · KININO 44 — 10.000 cx · KININO 58 — 8.000 cx.
📐 Some a medida inventada do modelo sem cadastro. No card do cliente, a caixa que não tem paletização aparecia como 1000×1200×1200mm — que não é medida real, é o valor padrão que o sistema usa quando não acha nada, e passava a impressão de que a caixa estava cadastrada certinho. Agora aparece "⚠️ caixa não cadastrada", sem número nenhum pra confundir.
🔍 Cliente sumia do Planejamento de Carga (BLUE SEA). A BLUE SEA tinha 36.500 caixas em produção e não aparecia no seletor de clientes. Causa: os pedidos vinham sem a caixa vinculada e o código não batia por causa do prefixo — pedido dizia 220064 LISA 24X8 e o cadastro tinha CX 220064 LISA 24X8. Sem achar a caixa, não há paletização, a carga vira 0 palete e o cliente era filtrado fora da tela. Agora o prefixo CX é opcional no casamento (o resto do código continua tendo que bater inteiro, e o cliente segue travado — nunca pega caixa de outro cliente).
⚠️ E o mais perigoso: agora ele AVISA em vez de esconder. Varrendo os dados reais, 11 dos 35 pedidos ativos não achavam a caixa no cadastro. Alguns clientes sumiam inteiros (BLUE SEA), mas outros era pior: a KININO aparecia normal com 8 paletes enquanto 3 pedidos dela — 30.000 caixas — eram descartados em silêncio, e você planejava o caminhão achando que aquilo era toda a carga. Agora o cliente aparece do mesmo jeito, com o aviso "⚠️ N cx sem paletização — cadastrar a caixa". Continuam de fora do cálculo (sem paletização não dá pra virar palete), mas você enxerga que existe carga ali. Restaram 6 casos onde o código realmente diverge (ex.: pedido KININO 44 × cadastro CX 01) — esses precisam de correção no cadastro, e o sistema não adivinha pra não herdar paletização errada.
🏷️ Etiqueta de palete por LOTE (pedido da Fezocar: palete grande, fábrica sem espaço). O operador libera de 15 em 15 e agora cada liberação é um lote com numeração própria — sai 1/15 a 15/15, e o lote seguinte recomeça do 1 com o selo LOTE 2. Antes o 2º lote saía errado: "16/15", "17/15".
🔢 O total agora é o que foi FEITO, não o que foi pedido. A plaquinha dizia "Total do pedido.: 3.000 cx" mesmo quando a produção fechou em 2.900. Agora saem duas linhas certas: "Lote 2: 15 paletes · 1.950 cx" (o que está indo neste caminhão) e "Total feito.: 2.900 cx" (o acumulado do pedido).
✍️ Último palete do lote sai EM ABERTO. Como quase sempre tem perda na produção, o último palete de cada lote é impresso com o campo de quantidade em branco e uma linha pra anotar à mão, marcado "PALETE EM ABERTO — ANOTAR". Os paletes cheios continuam saindo com a quantidade impressa normal.
📷 QR entende o lote (senão a Expedição travava). Como a numeração recomeça, o palete 1 do lote 2 teria o mesmo código do palete 1 do lote 1 — e o app recusaria dizendo "já bipado", justamente no 2º carregamento. O QR agora leva o número do lote. Etiquetas já impressas continuam valendo (o leitor entende os dois formatos), e pedido de lote único não muda em nada.
🔧 Botões que não abriam: consertados. O "🤖 Pergunte" e o "⚙️ Turnos & Capacidade" clicavam e não acontecia nada. Faltava um </div> no histórico de versões, e isso engolia 12 telas — junto com eles morreram também Tempos de Setup, RG da caixa, Caminhão, Escala, Coleta e as 4 telas de Orçamento. Todas voltaram.
📦 Expedição — Modo Carregamento ganhou a vista 3D. Na hora de bipar, o empilhadeirista agora alterna entre 🗺️ Planta e 📦 3D: dá pra ver os paletes empilhados dentro do baú, com o palete sólido = já bipado, cinza tracejado = pronto esperando e amarelo tracejado = ainda em produção. O espaço vazio no fundo do caminhão aparece no desenho.
🚦 Avisos durante o carregamento. Terminou um cliente, aparece "✅ Carga completa — Fulano. Próximo: Beltrano". Se os prontos dele já foram mas ainda tem coisa na máquina, aparece o aviso amarelo "prontos carregados; N paletes ainda em produção". No fim, "🏁 Caminhão carregado" — e se sobrou mercadoria, um aviso vermelho lista o que ficou pra trás e segue no estoque do PA (nada é baixado).
📊 Ordem de carregamento e contadores. Os clientes agora aparecem na ordem de carregar (a última entrega carrega primeiro, no fundo; a primeira entrega fica na porta) — antes era ordem alfabética. Cada cliente tem barra de progresso própria, e cada pilha na planta mostra quantos já foram bipados (ex.: 2/4), com contorno verde quando fecha.
🛡️ PCP reeditar plano não apaga mais a bipagem. Se o PCP abrisse um plano que a expedição já estava carregando e salvasse de novo, todos os paletes bipados sumiam e o carregamento voltava do zero. Agora o plano só anda pra frente (rascunho → liberado → carregando → concluído) e a bipagem é preservada.
🏭 As máquinas cadastradas somem do cronograma quando ficam sem pedido — corrigido. As 4 de fábrica sempre aparecem, mesmo paradas ("livre 2h12"). Já as cadastradas (offset, acopladeira, coladeira de visor) só tinham raia no dia em que tinham trabalho — bastava o último pedido delas terminar e elas desapareciam da régua, como se não existissem.
Agora toda máquina cadastrada e ativa tem raia fixa, igual às de fábrica. Máquina inativada no cadastro continua fora.
⚠️ Corrigir a produção estava DUPLICANDO o lançamento. Este é o mais sério do dia, porque mexia no número final.
• A correção mandava o identificador errado (o do servidor em vez do original do lançamento). Como não achava ninguém pra atualizar, a sincronização criava um lançamento novo — e o antigo continuava valendo. Um pedido corrigido de 7.000 pra 10.090 ficava com os dois, somando 17.090. Era daí que vinha o "Falta" com número negativo.
• Corrigido no PCP e nos dois caminhos do operador: agora usa o identificador certo e atualiza em vez de criar.
• A correção feita no PCP agora também chega no operador (quadro de concluídos + quantidade da etapa) — antes ela parava no banco e a próxima máquina seguia com o número velho. É o espelho do conserto que o operador ganhou na v2.37.67.
Pedidos corrigidos ANTES desta versão podem ter ficado com lançamento duplicado — vale conferir os que passaram por correção.
✏️ Corrigir a quantidade no operador estava morrendo na tela. A correção inteira só rodava se o pedido tivesse chegado ao aparelho com os lançamentos — e isso só acontece em pedido reprogramado. Em todos os outros casos o app mudava o número na tela e não salvava em lugar nenhum: nem na etapa (que a próxima máquina usa), nem no quadro de concluídos, nem no banco. Sem nenhum aviso.
• Agora a etapa e o quadro de concluídos são gravados sempre — eles só precisam do pedido e da máquina.
• O lançamento no banco, que precisa do identificador, é buscado na API quando não veio junto do pedido, em vez de desistir calado.
• Se ainda assim não achar, o app avisa ("corrigido aqui e pras próximas máquinas, mas confira no PCP") em vez de dizer que deu tudo certo.
✏️ Corrigir a quantidade agora chega nas outras máquinas e no PCP. O operador finalizava com 7.000, percebia o erro e corrigia pra 10.090 — a correção entrava no lançamento dele e no servidor, mas a quantidade da etapa continuava 7.000. Resultado: a acopladeira seguia trabalhando em cima do número velho e o PCP mostrava "7.000 / 10.000". Agora a correção grava pelos mesmos caminhos do finalizar (etapa + quadro de concluídos), então ela alcança a próxima máquina e a central.
🟣 Máquinas do meio ganharam cor no trilho do PCP. Elas ficavam no mesmo cinza de "aguardando" e sumiam entre o corte (verde) e o fechamento (azul) — dava a impressão de que o pedido nem passava por elas. Agora aparecem em roxo, deixando a rota inteira visível.
🏭 Dois acertos no app do operador, reportados no teste real:
• "AGUARDANDO CORTE E VINCO" mesmo esperando a offset. A mensagem só sabia dizer dois nomes — "Slotter" ou, em qualquer outro caso, "Corte e Vinco". Com uma máquina de corte cadastrada (offset, por exemplo), ela caía no segundo e mentia o nome. Agora mostra a máquina real do pedido: "⏳ AGUARDANDO OFFESET".
• "falta 0 pra fechar o pedido" no meio da tiragem. Ao liberar parcial, a conta usava a quantidade do pedido (1.000) em vez da chapa lançada (10.000) — então liberar 1.000 já dizia que não faltava nada. Agora usa a chapa, igual à barra e ao PCP: "falta 9.000 pra liberar tudo (10.000)".
Pedido em que a chapa é igual à quantidade (o dia a dia) continua mostrando exatamente o mesmo número de antes.
🧹 O botão "Atualizar app" agora fala com você — e funciona direito.
• Antes ele era mudo: limpava e recarregava sem dizer nada. Se o servidor ainda não tinha publicado a versão nova, o operador apertava, parecia que "não acontecia nada", e ficava sem saber se o problema era o app ou a publicação. Agora ele confere o servidor primeiro e responde: "você já está na mais nova (vX)", ou "versão nova! aparelho vX → servidor vY", ou "não consegui falar com o servidor".
• O aviso de versão nova (a tarja azul) estava mais fraco que o botão: mandava recarregar sem esperar a limpeza do cache terminar e sem desregistrar o service worker — a página recarregava antes de limpar, ainda controlada pela versão velha, e o app não atualizava. Corrigido nos 9 apps que têm esse aviso.
Se um aparelho ficar teimando numa versão antiga, fechar e abrir o app continua sendo o jeito mais garantido — mas agora deve ser raro precisar.
🔄 Reiniciar do zero agora limpa o aparelho do operador de verdade. Antes, mesmo depois de reiniciar, o celular continuava mostrando a produção velha — cronômetro de 34 horas correndo, "já feitas 3.456" — e ainda reenviava esse número por cima do zero. Acontecia nos dois aparelhos ao mesmo tempo.
• A regra ficou simples: em vez de carimbos e comparações, o sistema agora só pergunta "este trabalho nasceu antes ou depois do reinício?". Todo progresso já guarda a hora em que nasceu, então a limpeza é retroativa: o que está preso hoje se resolve sozinho na primeira sincronização, sem precisar reiniciar de novo.
• Dois operadores não entram mais no mesmo pedido. O reiniciar soltava a trava e ninguém a devolvia — o pedido ficava sem dono e qualquer um entrava, mesmo com alguém produzindo. Agora quem pega o pedido assume a trava de novo.
• Barra do PCP passou a medir contra a chapa lançada, igual ao app do operador: pedido de 1.000 com 10.000 chapas mostra 10%, não 100%. E a porcentagem agora aparece na linha.
Trabalho começado DEPOIS do reinício é preservado — a limpeza só alcança o que é anterior a ele. Troca de turno, reprogramar e reabrir etapa continuam funcionando igual.
🏭 Cada máquina com a sua própria vida. Três consertos no app do operador:
• "Já feitas" agora é POR MÁQUINA. Antes, se a offset tinha feito 200 caixas, a acopladeira e a coladeira mostravam "já feitas 200" também — emprestavam o número da máquina anterior. Agora cada uma mostra só o que ELA fez.
• Reiniciar do zero limpa o operador de verdade. Antes, um pedido reiniciado ainda aparecia como "Largado · 240 cx feitas" no aparelho do operador — sobrava o parcial antigo. Agora o reinício apaga esse resto, e se o operador estiver com o pedido aberto ele é avisado e volta pra lista. Também não deixa mais lançar produção de um pedido que acabou de ser zerado (nem no Finalizar, nem na Troca de turno).
• Coladeira de Visor não pede mais paletização. Ela é máquina do MEIO, mas o sistema a confundia com a Coladeira de fechamento. Agora quem paletiza é definido pelo tipo no cadastro da máquina.
A troca de turno normal (largar com produção e o próximo continuar de onde parou) segue funcionando igual. Preparo da FASE 5: a entrada no estoque de produto acabado passou a usar a etapa final da sequência, abrindo caminho pra máquina de fechamento cadastrada.
📋 Vida da Caixa (o RG do pedido) mostra as máquinas novas. Começa a FASE 5 do Roteiro Livre. Antes o RG espremia tudo em "Slotter" + "Coladeira" e a Acopladeira (ou verniz, offset…) sumia. Agora cada máquina da rota vira uma estação própria na ordem certa (corte → meio → fechamento), com o nome/ícone do cadastro, quem rodou, quanto produziu e as ocorrências dela. Pedido de 2 etapas continua idêntico; e uma ocorrência que o RG antigo escondia agora aparece (nenhuma se perde).
🏭 Cronograma: a máquina de CORTE cadastrada (offset) agora tem RAIA própria. Fecha 100% a FASE 4 do Roteiro Livre. Antes o corte da offset aparecia na raia do Slotter; agora ela tem a raia própria na régua, com o estado ao vivo (lido da produção que o operador lança) e a velocidade do cadastro dela. Pedido que usa Slotter/Corte e Vinco continua exatamente igual.
Agora TODAS as máquinas cadastradas (corte, meio e fim¹) aparecem no cronograma automático — cadastrar uma nova já funciona sozinho. (¹ máquina de fechamento custom ainda é da FASE 5.)
📄 Romaneio por cliente na expedição. Imprime o romaneio (o que vai no caminhão) separado por cliente — produto, medida, qualidade (onda), paletes, caixas, peso e total. Cabeçalho com nº sequencial (Romaneio Nº 21, 22…), caminhão + placa + tamanho do baú e motorista. Canhoto com o nº do romaneio, a lista numerada dos itens (rastreabilidade) e campos de assinatura: Carregado por (empilhadeirista) — já preenchido quando a carga foi bipada, em branco no plano —, Conferido por, Encarregado e Recebido por (cliente). Botão por cliente no histórico do plano e na carga bipada/manual (funciona até sem plano). No romaneio do plano, mostra o desenho do caminhão com a carga do cliente em destaque e as outras transparentes (ordem de entrega: PORTA = 1ª, fundo = última). O nº do pedido aparece em todos os casos — no plano (busca por cliente+código) e nas cargas já carregadas (deriva do pedido). Histórico de romaneios reimprimível.
🏭 Cronograma: a etapa do meio agora tem RAIA própria na régua. Fecha a FASE 4 do Roteiro Livre. A máquina do meio (Acopladeira etc.) aparece como raia posicionada na linha do tempo — na ordem certa (corte → meio → acabamento), sem sobrepor outros pedidos e sem "raia-fantasma" (só aparece nos dias em que roda). O acabamento agora espera o meio, e o resumo mostra o "Livre" da máquina do meio. Pedido de 2 etapas continua exatamente igual.
Falta só a máquina de CORTE cadastrada (offset) ganhar raia própria — hoje ela ainda aparece na raia do Slotter.
🏭 Cronograma mostra as etapas do meio (Acopladeira, coladeira de visor…). Pedido com roteiro de 3+ etapas agora aparece no card do cronograma na ordem certa — corte → meio → acabamento — e a etapa do meio mostra o status ao vivo (aguardando / em produção % / concluído), lido direto da produção do operador. É a FASE 4 do Roteiro Livre chegando no cronograma.
Por ora a etapa do meio aparece como linha de status no card (a raia própria dela na régua vem no próximo passo). Pedido de 2 etapas continua exatamente igual.
🏁 Resumo do turno do operador reformulado — agora puxa tudo do banco de dados (não mais do aparelho): produção do dia por máquina, paradas completas por motivo (do pedido + livres) e tempo produtivo × parado.
🎯 Meta do turno (vinda do cronograma inteligente): caixas e pedidos previstos por máquina/turno, com barra de % do que foi cumprido.
📅 Histórico por data — o operador navega pra dias anteriores ("o que fiz ontem?") e vê o relatório daquele dia.
Requer restart da API (rota nova /api/operador-app/resumo-dia).
🔵 Pedido reiniciado não fica mais "rodando" na máquina. Depois de reiniciar, o card às vezes continuava mostrando "🔵 Rodando na Acopladeira" (ou na máquina que estava) mesmo com a produção já zerada. Causa: quando a trava do operador é solta (ao reiniciar, reprogramar ou destravar no 🔓), o registro do operador guardava o "início de produção" e o painel lia isso como se ainda estivesse rodando. Agora, trava solta = não está rodando: o card mostra a fase real pelo status do pedido (reiniciado → "A Programar"). Também não conta mais o "parcial ao vivo" de uma trava já solta na barra de progresso.
🔄 Reiniciar agora zera o pedido DE VERDADE. Antes o Reiniciar deixava lixo pra trás (o pedido continuava "rodando" numa etapa mesmo depois de zerado). Agora ele apaga tudo: produção de todas as máquinas (cancelada), o que já tinha ido pro estoque, as etapas concluídas/liberadas de cada máquina que passou (limpa o "liberado" que ficava preso), e tira o material disponível — o pedido volta pra "A Programar" (precisa lançar a chapa de novo). A programação (cortes/bobina) é mantida. O aviso de confirmação lista tudo que vai ser apagado.
🖨️ Máquina de corte cadastrada (ex: offset) entra como 1ª máquina. Agora o menu "1ª máquina (corte)" do pedido mostra, além do Slotter e do Corte e Vinco, as máquinas que você cadastrou como Corte / preparação (ex: offset). Ela ocupa o lugar do corte — a produção dela conta como chapa e o pedido flui igual. O sistema passou a respeitar a posição no fluxo de cada máquina cadastrada: corte vai na 1ª máquina, meio vai em "processo do meio", fim (fechamento próprio) fica pra próxima fase. Pedidos e máquinas de fábrica continuam idênticos.
🔢 Cada etapa trabalha o que a ANTERIOR liberou (Roteiro Livre). No teste da Acopladeira apareceu: liberou 500 pra próxima e a Coladeira mostrava 1.000. Era porque toda etapa olhava sempre pro Slotter em vez de quem liberou pra ela. Agora a base de cada etapa (paletização/quantidade) é o que a etapa imediatamente anterior da sequência liberou ou concluiu — Acopladeira liberou 500 → a Coladeira seguinte trabalha 500. Pedido normal (Slotter → Coladeira) continua idêntico. Testado com o dado real do pedido teste.
🧩 Trilho de processo do PCP mostra a sequência completa. Na coluna PROCESSO / PROGRESSO (Relatório/PCP), o trilho de etapas agora mostra os processos do meio — ex: Slotter → 🩹 Acopladeira → 📦 Coladeira, em vez de pular direto pra Coladeira. Quando a etapa do meio está rodando, ela pulsa no trilho igual às de fábrica. Vale também no texto do cronograma/WhatsApp. Pedidos sem sequência continuam idênticos. (Completa a FASE 2/3 do Roteiro Livre.)
🏭 Operador segue a sequência — FASE 3 do Roteiro Livre. O app do operador agora entende as máquinas cadastradas (Acopladeira, Verniz…): o operador vinculado a elas vê os pedidos cuja sequência tem a etapa dele, e o gating virou genérico — cada etapa espera a anterior da sequência (concluída ou com liberação parcial), não mais só o Slotter. Ex.: numa sequência Slotter → Acopladeira → Coladeira, a Coladeira espera a Acopladeira (mostra "⏳ AGUARDANDO ACOPLADEIRA"). A liberação parcial também ficou genérica: qualquer etapa não-final libera pra próxima (somando, como sempre). Conclusão de etapa do meio conta com geração/reabertura igual às de fábrica. Pedidos e máquinas de hoje: comportamento idêntico (testado caso a caso). ⚠️ Requer teste em 2 aparelhos antes de rodar de verdade; falta a FASE 4 (lane no cronograma).
🧩 Sequência de processos no pedido — FASE 2 do Roteiro Livre. No cadastro do pedido, o Roteiro ganhou a opção "Sequência personalizada": o corte entra automático, você adiciona os processos do meio (Acopladeira, Verniz… — os que cadastrou em Máquinas/Processos), ordena com ◀ ▶, e escolhe o fechamento (Coladeira/Grampeadeira). A sequência aparece no preview do fluxo, no card do pedido (corte → acopladeira → coladeira) e é publicada pro app do operador (que ganha as etapas novas na FASE 3; até lá, o fluxo do operador segue como hoje — por isso o fechamento ainda é Coladeira/Grampeadeira). Pedidos antigos não mudam nada.
⚙️
Cadastro de Máquinas / Processos — FASE 1 do Roteiro Livre. Tela nova em
Cadastros → Máquinas / Processos: além das 4 de fábrica (Slotter, Corte e Vinco, Coladeira, Grampeadeira), agora dá pra
cadastrar processos novos — Acopladeira, Verniz, Coladeira de Visor, etc. — com ícone, posição no fluxo (corte / meio / fechamento) e velocidade padrão. As máquinas novas já aparecem nas listas de máquina do sistema.
Próximas fases: montar a sequência de processos por pedido (na ordem que quiser), o app do operador seguir a sequência e o cronograma ganhar as lanes novas. Nada do fluxo atual muda nesta fase.
🟠 Palete fora do padrão avisado NA CHEGADA do pedido. Quando entra um pedido de caixa que usa palete diferente do PBR (ex: 800×1400), o card do pedido no Relatório/PCP já mostra o aviso laranja com a conta pronta ("providenciar 7 paletes antes da produção") — sem esperar abrir o cadastro da caixa ou o operador pegar o pedido. O aviso some sozinho quando o pedido entra em produção (daí o app do operador segue mostrando o dele).
🏷️ QR da etiqueta de palete: consertado e agora feito DENTRO do sistema. A etiqueta dependia de um site externo pra desenhar o QR — quando ele falhava (como na impressão do pedido 23551), o QR saía pequeno, torto ou em branco. Agora o QR é gerado na própria etiqueta, na hora, sem internet e sem espera: sai sempre grande e nítido na moldura. Testado de ponta a ponta: o QR gerado foi lido de volta pelo mesmo leitor da Expedição (inclusive nomes com acento e códigos longos). As etiquetas já impressas continuam valendo.
🕓 Aviso ao editar uma carga antiga já entregue. Quando você clica em Editar numa carga do histórico cujos pedidos já foram entregues/carregados, o editor mostrava tudo zerado e parecia bug. Agora aparece um aviso explicando: o Planejamento recalcula com o que está pendente hoje (por isso zera), e pra ver como a carga estava é só usar o 👁 Ver do histórico. Nada quebrado — a carga tinha saído mesmo.
📋 Histórico de cargas no Planejamento de Carga. Agora aparece a lista de tudo que você já montou — cada carga com caminhão, status, data, quem salvou, nº de paletes e os clientes. Cada uma tem 👁 Ver (abre um resumo do que foi: o que vai por cliente, "3 de 3 vão", prioridade, ficou pra trás) e ✏️ Editar — dá pra editar mesmo depois de liberado (trocar caminhão, trocar/adicionar cliente, marcar prioridade) e é só Salvar ou Liberar de novo pra atualizar. Também dá pra imprimir 🖨️ ou remover 🗑 uma carga do histórico. (Substitui os "chips" pequenininhos de antes.)
⌨️ Fim do histórico repetido do navegador nos apps também. Estendi o autocomplete desligado pros aplicativos separados: as buscas de cliente/código na Expedição e na Qualidade, a busca de cliente do Vendedor (e o "tipo de caixa"), e as buscas do Almoxarifado e de Compras. Agora nenhum campo do sistema sugere mais aqueles nomes repetidos do navegador — em todos os apps.
⌨️ Autocomplete de cliente e caixa direto do cadastro (não mais do navegador). Todo campo onde você digita o nome do cliente ou a caixa/referência passou a sugerir direto do cadastro do sistema — conforme digita, abre o menu com os nomes reais, e clicando ele completa sozinho. Acabou o histórico repetido do navegador (aquele que mostrava o mesmo nome várias vezes): todos os campos ganharam autocomplete desligado. Já valia no pedido, orçamento, cadastro de caixa e custos; agora também na etiqueta avulsa (cliente + caixa, com a caixa filtrada pelo cliente digitado), no Setup por cliente, na divisão de papel e nas buscas. Um mecanismo central preenche o menu na hora que você clica no campo, sempre atualizado com o cadastro.
📊 Barra de porcentagem em cada etapa do Cronograma. Agora cada máquina mostra uma barra de progresso com o % do que já foi feito e ela fica sempre visível (antes sumia quando concluía). Slotter que cortou 5.000 de 10.000 = 50%; Coladeira/Grampeadeira idem, conforme os paletes vão sendo lançados. Enquanto o operador ainda não lançou nada mas a máquina já está rodando, aparece uma estimativa por tempo (velocidade do cadastro × tempo rodando), com barra listrada e a marca "estimado pelo tempo" — quando o lançamento real chega, a barra passa a contar por caixa. Etapa concluída mostra 100%. (Primeiro passo pro futuro sensor da Slotter atualizar o % em tempo real.)
🏷️ Etiqueta do palete: logo e textos ocupando o espaço todo. A logo do cliente passou a usar o card inteiro (o rótulo "Cliente.:" virou marquinha no canto), e o sistema apara sozinho a margem branca embutida no arquivo da logo pra ela sair grande. A Referência e o Palet Nº agora crescem sozinhos pra preencher o card (texto curto fica gigante, texto longo diminui sem estourar). No card da quantidade aparece o Total do pedido. E o nome do cliente por escrito saiu pro rodapé (junto de Operador e Data), garantindo identificação mesmo quando só a logo aparece no topo. Lembrete: as Medidas internas vêm do cadastro da caixa (C×L×A) — caixa sem medidas mostra o nome do cliente.
🏷️ Etiqueta do palete redesenhada (layout novo, aprovado no editor). A ficha do palete foi remontada exatamente no formato que você desenhou: logo do cliente bem grande no topo, Nº interno + Medidas internas lado a lado, Referência gigante no meio, e embaixo o QR à esquerda (bipa de longe) com Palet Nº e Quantidade no Palet (em vermelho) à direita, mais o rodapé com Operador e Data. Vale nas etiquetas do PCP e do operador. Textos e números se ajustam sozinhos pra não estourar (referência/quantidade longas diminuem a fonte). Quem não tem logo cadastrada continua mostrando o nome do cliente.
🏷️
Etiqueta de palete no novo layout (padrão FK). A ficha do palete (que sai da Coladeira/Grampeadeira e do PCP) foi redesenhada igual ao modelo aprovado: cards azuis com Cliente + logo + QR ao lado, Nº interno, Medidas internas da caixa (C×L×A), Referência grande, Quantidade no palet em vermelho e Palet Nº. O QR continua o mesmo (bipa de ~2m). Medidas puxadas do cadastro da caixa (casando código + cliente, sem cross-client).
📤
Liberação parcial agora SOMA. O Slotter libera em várias rodadas; o app gravava só a ÚLTIMA (liberou 1.000 oito vezes → ficava 1.000, os outros 7.000 sumiam — confirmado no pedido 23551). Agora ele pergunta só
quanto está liberando AGORA, mostra o que já foi liberado e
soma sozinho. Na hora de finalizar aparece
"você já liberou X · falta Y pra fechar o pedido", e o ajuste continua descontando
uma vez só.
↩️
Reabrir etapa — quando a máquina quebra no meio. Se a operadora finaliza a etapa mas o processo anterior entregou MAIS (ex.: o Slotter cortou 2.320 e a Grampeadeira só grampeou 260 porque a máquina quebrou), o pedido travava e
não existia caminho pela tela — nem o PCP conseguia soltar. Agora o pedido tem o botão
↩️ Reabrir · terminar X, que devolve o pedido pro operador com a conta certa (
2.060 no exemplo) e sem perder nada do que já foi lançado. Vale pra
Grampeadeira, Coladeira e Slotter: reabrindo o Slotter, o que ele já cortou fica
liberado pra próxima etapa trabalhar em paralelo enquanto ele corta o resto.
📋 Resumo do operador agora é o DIA todo, separado por máquina. No fim do turno ele vê um bloco TOTAL DO DIA e um bloco por máquina — quem rodou no Slotter de manhã e na Grampeadeira à tarde não perde mais metade do dia no resumo. Também corrigido o "Tempo em ajustes: 6435h" (268 dias!): um ajuste esquecido aberto meses atrás entrava na conta de hoje.
🏷️ Etiqueta do palete: QR que bipa de longe. O QR guardava dado repetido à toa e saía com quadradinhos de 1mm — só lia a ~40cm. Agora tem 112mm com quadradinhos 3,3× maiores, impressão nítida e margem correta: dá pra bipar de ~2m, de cima da empilhadeira. As etiquetas já impressas continuam valendo (o leitor entende os dois formatos).
🧹 Projetar Corte e Vinco: padrão Maleta + sem "riscos" quando não tem medida. A tela de projeto agora abre com o gerador Maleta por padrão, e enquanto você não informar as medidas internas (C, L, A) ela não desenha aquele emaranhado de linhas — mostra o aviso "informe as medidas" e o molde fica "—". Assim que você digita C×L×A, o desenho aparece certinho.
📐 Corte e Vinco no orçamento: chapa do plano inteiro + preço por poses. Agora a medida da chapa no orçamento é a do plano inteiro (ex.: 1131 × 812, com o refile), e o peso e o preço são divididos pelas poses (2, 4…) pra dar o valor por caixa certo — sai o mesmo preço de antes, mas mostrando a medida real. As poses ficam guardadas na caixa pra a Programação depois tirar caixas ÷ poses = chapas (10.000 caixas → 5.000 chapas de 812). Obs.: na Programação, "cortes" é o corte da onduladeira (chapas na largura da bobina) — coisa diferente das poses da faca; a divisão por poses da produção vem no próximo passo.
🎨 Projetar Corte e Vinco: guarda o projeto + desenha o plano no orçamento. Agora ao reabrir 🎨 Projetar (pra editar ou depois de "atualizar item") ele volta com tudo que você já fez — modelo, DXF, poses, encaixe, preços e o desenho — em vez de resetar. E o desenho do plano real (com as poses/encaixe) passa a aparecer no orçamento, no lugar do retângulo simples.
🐛 Correção: tela "Projetar Corte e Vinco" não carregava a biblioteca/modelos. O modal do cadastro de caixa fica escondido no fundo depois de aberto uma vez e usava os mesmos identificadores da tela de projeto — então a biblioteca e os cálculos iam pro lugar invisível. Agora a tela de projeto limpa esse resquício ao abrir e mostra a biblioteca, o DXF, os geradores e os cálculos direitinho.
🎨
Projetar Corte e Vinco dentro do orçamento. No item Corte e Vinco tem agora o botão
🎨 Projetar Corte e Vinco, que abre a
tela completa de projeto (biblioteca, gerador, DXF, poses, encaixe, refile e preços) — igual à do cadastro de caixa. Você faz todo o arranjo ali e ao
Aplicar ele joga pro orçamento a
chapa (comp/larg), a faca, a área e o material.
Não precisa mais ter a caixa cadastrada — dá pra projetar do zero num cliente novo. Se quiser, marque
"Salvar também no cadastro de caixas" pra criar a caixa junto. O atalho de puxar de uma caixa já cadastrada continua, como opção.
🚚 Planejamento de Carga: card mais claro + imprimir plano. Cada caixa agora mostra quantos paletes daquele modelo realmente vão no caminhão (✅ todos · ⚠️ parte · ⬜ nenhum), no lugar de só o total. E tem o botão 🖨️ Imprimir plano, que gera um PDF com o caminhão, as medidas do baú, o que vai / o que ficou pra trás e os desenhos 2D e 3D — pronto pra imprimir ou salvar. O empacotador também passou a seguir a acomodação real da caixa e a escolher a melhor orientação do palete no baú.
💰 Corte e Vinco no Orçamento + importação em lote (Fase 5 — última). No item do orçamento tipo Corte e Vinco tem o botão 🔗 Puxar da caixa: escolhe a caixa cadastrada (só do mesmo cliente) e já traz a medida da chapa por caixa (com poses/encaixe/refile embutidos), a faca (perguntando se dilui no programa ou cobra à parte, pela diluição de ferramental que já existe) e o ganho de apara abatido do preço. E a importação em lote: botão ✂️ Importar Corte e Vinco (lote) no cadastro de caixas — baixe o modelo CSV, preencha uma caixa por linha, selecione o CSV + os DXFs (casados pelo nome do arquivo) e confira o preview antes de criar. Fecha o módulo Corte e Vinco (fases 1 a 5).
🧩 Corte e Vinco — poses, encaixe e custos (Fase 4). Agora dá pra definir o arranjo na faca: poses no comprimento × na largura, espaço entre poses e refile (comprimento e largura). O encaixe (fileiras invertidas 180°) tem o botão 🧮 Calcular melhor encaixe que acha sozinho a sobreposição e o deslocamento pelo DXF. E os custos: 🔪 faca (lâmina total × R$/m, padrão R$ 120/m), chapa por caixa (área × gramatura × R$/kg ÷ poses) e o ganho com apara abatido — dando o custo líquido por caixa. Testado: encaixe 2×2 do fundo americano → largura 843,5; melhor encaixe do DXF → sobrep 168,5 / desloc 584; faca da caixa de linguiça @120/m = R$ 1.110,81. Próxima (Fase 5): plugar no Orçamento Inteligente + importar a planilha em lote.
📐 Corte e Vinco — importar DXF do ArtiosCAD (Fase 3). Agora dá pra arrastar o .dxf no cadastro Corte e Vinco: o sistema lê o desenho exato (linhas, arcos, polilinhas) e mostra o molde real da faca com o desenho idêntico ao projeto. As camadas viram uma tabela onde cada uma é Corte / Vinco / Picote 5×5 / Ignorar (com palpite automático pela cor — cor 1 corte, 2 vinco, 3/85 picote, "Unknown" ignora — e dropdown pra corrigir). O picote entra na lâmina (tracejado laranja). Testado nos DXF reais: fundo americano → 718×423,5 (corte 2.984,7 · vinco 1.983,0 · picote 348) e caixa de linguiça → 645,5×566,8 · lâmina 9,26 m. Próxima: poses/encaixe/refile e custos no orçamento.
📚 Corte e Vinco — biblioteca de modelos (Fase 2). No cadastro Corte e Vinco tem agora a biblioteca com 545 modelos FEFCO/ECMA (366 com miniatura), com busca por código/nome e filtro por série (01–09 + ECMA). Clicar num modelo já puxa o gerador (fundo americano/maleta) quando tem fórmula. Os ★ mais usados viram chips de acesso rápido no topo — a contagem é por usuário e fica salva no banco (não some ao trocar de aparelho). Próximas fases: importar DXF do ArtiosCAD, poses/encaixe e custos no orçamento.
✂️ Corte e Vinco no cadastro de caixa (Fase 1). No modelo Corte e Vinco, dá pra escolher um gerador de chapa — Fundo Americano (ECMA A55.20.01.01 / FEFCO 0711) ou Maleta FEFCO 0201 — que calcula a chapa do molde pela fórmula a partir das medidas internas (C×L×A) + onda. Mostra a planificação desenhada com cotas (abas, travas, fundo, vincos), permite ajustar na mão a medida de 1 caixa, e calcula área/peso da chapa. Calibrado: 300×200×150 onda B → chapa 1018 × 508,5 mm. Tudo aditivo — caixas normais (dobra/slotter) seguem iguais. Próximas fases: biblioteca de modelos, importar DXF do ArtiosCAD, poses/encaixe e custos no orçamento.
📦 Planejamento de Carga: conta por caixas + palete PARCIAL. Agora cada modelo do cliente mostra a conta a partir da quantidade de caixas (prontas + em produção) convertida em paletes: ex. 56.350 cx ÷ 5.250/palete → 10× 2,40m + 1× PARCIAL 1,80m (3.850 cx · 11/15 camadas). O último palete parcial (mais baixo, com menos camadas) entra no plano como peça própria — pode empilhar onde o cheio não cabe — e só fica pronto quando toda a quantidade foi produzida. Cheio e parcial são contados separados (sem misturar) e a planta mostra o ·P no parcial.
⭐ Caixa prioritária no Planejamento de Carga. Dentro de cada cliente, cada caixa agora tem uma estrela: marcou = essa caixa TEM que ir, sem exceção. Quando o caminhão não cabe tudo, o sistema garante a caixa prioritária e derruba as outras no lugar dela (as não-prioritárias é que ficam pra trás). Se uma prioritária não couber nem fisicamente, aparece um alerta forte pra usar outro caminhão ou fazer 2 viagens. A prioridade fica guardada quando você salva o plano.
🔄 Coletas no Retorno (Expedição · Fase 4 — caminhão nunca volta vazio nem esquecido). Fluxo completo em 4 apps: (1) na Escala (aqui na central), cada viagem ganhou + adicionar retorno — o PCP registra o que coletar, onde e o destino interno; (2) o motorista vê a coleta junto da entrega e marca 📦 Coleta feita → 🏭 Cheguei na fábrica; (3) a Expedição recebe um 🔔 alerta pulsante, 📤 retira do caminhão e 📦 encaminha ao almoxarifado; (4) o Almoxarifado ganhou a aba 🚚 Coletas com a fila pra dar ✅ Recebi. Cada passo guarda hora + quem fez (linha do tempo). Tudo novo, não mexe em nada que já existe.
🚚 Planejamento de Carga: vista 3D + clientes automáticos da escala (Fase 2 completa). Duas melhorias na aba: (1) desenho 3D (isométrico) mostrando como os paletes ficam empilhados no baú — sólido = pronto, fantasma = em produção, com estrado de madeira; (2) ao escolher o caminhão (ou "Novo plano"), o sistema já puxa os clientes da viagem daquele caminhão na escala, na ordem de entrega, só quem tem carga (com botão 🔄 Puxar da escala pra puxar de novo). Ignora viagem cancelada/entregue, casa o nome do cliente mesmo com acento/abreviação diferente, e avisa quando o caminhão não tem viagem na escala.
📦 Modo Carregamento (Expedição · Fase 3 — bipagem do empilhadeirista). No app da Expedição tem um card novo 🗓️ Carregar por Plano (com contador de planos liberados). O empilhadeirista abre o plano liberado do dia, vê a planta do baú (🟩 bipado · ⬜ pronto esperando · 🟨 em produção) e bipa cada palete com a câmera. O sistema confere se o palete é daquele plano (avisa se for de outro cliente/caixa) e se já foi bipado, mostra o progresso por cliente em tempo real, e no fim 🏁 Caminhão carregado fecha o plano. Cada bipagem guarda palete/hora/quem — e fica salva no aparelho se a internet cair.
💾 Planejamento de Carga: salvar e liberar o plano (Expedição · ponte pra bipagem). Depois de montar a carga, dá pra 💾 Salvar rascunho e 🚚 Liberar pro carregamento — o plano fica guardado com um status (rascunho → liberado). Os planos salvos viram atalhos pra reabrir na hora. É a base pra a próxima parte: o Modo Carregamento, onde o empilhadeirista bipa cada palete seguindo o plano liberado.
🗓️ Planejamento de Carga (Expedição · Fase 2, parte 1). Aba nova em Expedição → Planejamento de Carga: escolhe o caminhão do cadastro (com o baú da Fase 1), adiciona os clientes da entrega (só quem tem carga programada), vê por modelo os ✅ paletes prontos + 🏭 em produção, define a ordem de entrega (a 1ª fica na porta, a última no fundo), e o sistema calcula o encaixe automático (skyline) + a planta do piso + o que ficou pra trás (sem baixar do estoque). Ainda vem: o desenho isométrico 3D, salvar o plano e a herança automática dos clientes da escala.
🚛 Expedição — Fase 1 (base do Planejamento de Carga). Início do novo módulo (invisível no dia a dia por enquanto): (1) o cadastro do caminhão — na central e no app da Escala — ganhou as medidas internas do baú (Comprimento × Largura × Altura em mm, opcional; caminhão antigo sem medidas continua funcionando); (2) cada entrega da escala agora tem um id estável (antes era identificada só pela posição, que quebrava ao remover uma entrega do meio) — pra a coleta de retorno grudar na entrega certa mais pra frente. As medidas do baú são copiadas na viagem ao salvar. Nada muda no uso atual da escala.
💰 Orçamentos aparecem NA HORA. Os orçamentos já cadastrados não carregavam de imediato — o número no menu ficava 0 e a lista só surgia depois de você mexer na aba. Agora (1) o número no menu atualiza assim que os orçamentos chegam do servidor (mesmo no Dashboard) e (2) ao abrir a aba Orçamentos, a lista já renderiza na hora com o que está cadastrado. Não precisa mais clicar em "Novo Orçamento" pra eles aparecerem.
🔀 Cronograma respeita a Ordem de Produção (parou de perder a ordem salva). A ordem que você define no Reordenar (arrastar/setas + Salvar) estava sendo apagada quando um aparelho publicava config sem ter a ordem carregada — aí o cronograma caía na prioridade por data (mais atrasado primeiro), ignorando o que você definiu. Corrigido: a publicação de config agora preserva a ordem salva. Depois de atualizar, abra Reordenar, ajuste e Salve — agora ela fica e o cronograma segue ela (1º = 1º, 2º = 2º…), independente de chapa/atraso.
🔄 Cronograma ORGÂNICO: cada pedido no horário REAL. O cronograma do dia agora reflete a realidade: pedido feito aparece no horário que realmente rodou (não no plano — ex.: o XPLASTZ na manhã), pedido rodando mostra até onde vai, e o que ainda não começou PUXA pra frente sem vão à toa (pulando almoço). Cada etapa ganha selo ⚡ Antecipado (começou antes do plano) ou 🟠 Atrasado (depois), e o acabamento espera o corte. O registro do dia passado e a previsão do futuro seguem pelo plano.
🧹 Cronograma: pedido PRONTO sai do dia (mostra só o que falta). Um pedido que já ficou pronto (ou pronto p/ carregar / carregado / entregue) sai do cronograma do dia ativo — ex.: o XPLASTZ ficou pronto antes do almoço e continuava aparecendo às 12h-13h como se fosse rodar. Agora o dia mostra só o que falta fazer (programado, material c/ chapa, em produção). O registro do dia passado continua mostrando tudo que rodou.
📦 Cronograma: caixas prontas + paletes no card do acabamento. No card do cronograma, o bloco de Acabamento (Coladeira/Grampeadeira) agora mostra ✅ X cx prontas · 📦 Y paletes p/ carregar 🚚 — as caixas prontas aparecem sempre; o nº de paletes aparece quando o operador etiqueta os paletes. Ajuda a expedição a planejar a carga do caminhão sem sair do cronograma.
🗓️ Cronograma: pedido reprogramado SEM chapa some do cronograma. O cronograma do dia é congelado (uma âncora, pra não ficar dançando). Um pedido que foi reprogramado e ficou sem chapa (ex.: KININO CX 08) continuava aparecendo no cronograma mesmo sem poder rodar. Agora ele sai do cronograma assim que fica sem chapa e volta sozinho quando o PCP lança a chapa do que falta. O que já rodou de verdade hoje nunca some (não apaga produção real).
🔄 Reprogramar parcial refeito (POWERDENT). Agora o operador não reprograma mais — só finaliza o que fez. Quem reprograma é o PCP, no painel: botão 🔄 Reprogramar · falta mostra Pedido · Feito · Falta e deixa lançar a chapa do que falta. O mesmo pedido continua e a produção já feita nunca é apagada (sempre soma). Com chapa lançada ele volta pro operador produzir o que falta e o fluxo Slotter → Coladeira recomeça certinho. Corrige o caso do 3.800 que se perdia no "Reiniciar".
⏱ Cronograma: hora programada + hora feita. Nos cards do cronograma (espelho do operador e no PDF), quando um pedido já começou ou terminou, além da hora programada agora aparece também a hora que foi feita de verdade pelo operador (em verde, ex.: "feito 14:05→15:10"). Assim dá pra comparar o planejado com o real de cada máquina.
🗓️ Cronograma segue a Ordem de Produção + data no PDF. O cronograma agora respeita a ordem que você define em "Ordem de Produção" (o que já está em produção fica no topo; o resto entra na ordem que você arrastou; quem não está na lista vai pro fim). E ao salvar em PDF (🖨 Dia / 📅 Semana), o arquivo já sai com a data no nome (ex.: "Cronograma 14-07-2026").
🗓️ Cronograma: só entra o que dá pra produzir. O cronograma agora mostra só programado, material disponível (com chapa) e em produção — igual ao operador. Um pedido "esperando programação" (material disponível sem chapa) não aparece mais no cronograma (era o caso do KININO CX 08, que estava no cronograma mas não ia pro operador).
⏱ Cronograma: re-aloca no atraso + almoço do 2º turno. Agora, no dia de hoje, quando um pedido atrasa, os pedidos que ainda não começaram naquela máquina deslizam sozinhos pra acompanhar o atraso (com contorno tracejado); o que já está rodando ou pronto fica no lugar. O acabamento acompanha o atraso do corte (nunca aparece antes dele), e a barra e o card sempre mostram o mesmo horário. Barra re-alocada não passa do fim do turno (a régua não estica). No ⏱ Turnos por máquina, novo campo "Almoço às (2º turno)" (inclusive de madrugada). Motor testado (46 checagens) e revisado adversarial (3 correções).
🖨 Cronograma: impressão IGUAL À TELA. Os botões 🖨 Dia e 📅 Semana agora imprimem a mesma linha do tempo da tela — as 4 raias com as barras coloridas por máquina (com o horário certinho), o almoço e a parte fechada de cada máquina, mais os cards dos pedidos em 2 colunas — tudo em folha A4 branca, uma página por dia. Antes saía uma lista simples. Revisado (a impressão força as cores do fundo pra as barras não sumirem no PDF; dia passado sai como é o registro).
⏱ Cronograma: turno por máquina. Agora cada máquina (Slotter, Corte e Vinco, Coladeira, Grampeadeira) pode ter horário próprio — a Coladeira fecha cedo e o Slotter segue à noite no mesmo dia, deixando o cronograma mais preciso. No cronograma tem o botão ⏱ Turnos: marque uma máquina pra dar a ela um turno próprio (turnos, horário de início, horas, almoço); sem marcar, ela usa o turno geral das Configurações (nada muda pra quem não mexer). Cada raia mostra a janela dela (a parte fechada fica escurecida). Motor testado (22 checagens) e revisado.
🚀 Orçamento Inteligente — Fase 5: orçamento aprovado vira pedido no Cronograma. No orçamento aprovado, o botão Gerar pedidos abre uma telinha pra confirmar a data da 1ª entrega e o acabamento de cada item, e cria os pedidos já programados no Cronograma (com a velocidade certa da máquina, sem o ⚠️). Orçamento com programa de entregas gera um pedido por entrega, com as datas escalonadas. Cada pedido fica amarrado ao orçamento e tem trava pra não gerar duplicado. A ferramenta "à parte" não vira pedido — fica anotada como cobrança única. Fecha o Orçamento Inteligente (fases 1 a 5).
💰 Orçamento Inteligente — Fase 4: programação de entregas. Quando o item tem clichê/faca "diluir", aparece um painel pra montar um programa de entregas (ex.: 3 entregas de 10.000): a ferramenta dilui em TODAS as entregas, o preço fica menor e o cliente paga o mesmo em toda entrega. A nota mostra só a condição ("mínimo de N entregas, mesmo preço"). Tem uma visão interna (só na tela) mostrando quando a ferramenta se paga e o ganho extra depois disso. Nada do que já existia muda.
💰 Orçamento Inteligente — Fase 3: IPI do cliente + condição de pagamento. Ao escolher o cliente no orçamento, o sistema já sabe se ele tem carta de isenção de IPI válida (marca "sem IPI" sozinho e avisa se a carta está pra vencer) ou se a carta venceu (volta a cobrar e avisa). Novo campo 💳 Condição de pagamento puxado do cadastro do cliente (ou do padrão do sistema), que agora aparece na nota e no WhatsApp. Nada do que já existia muda — é só acréscimo.
💰 Orçamento Inteligente — Fase 2: assistente de preço + simulador. No item do orçamento, o painel 💡 Preço inteligente monta o preço/un sozinho (papel com faixa de desconto + setup + frete + clichê/faca), o botão 📊 Simular quantidades compara faixas lado a lado, e dá pra guardar clichê/faca (diluir ou à parte), cores, peso do pedido e observações (tudo na nota + WhatsApp). A nota do cliente NÃO mostra a chapa. Nada do orçamento atual muda — é só acréscimo.
🎨 Ajuste de layout da Config. Orçamento — as faixas de desconto e o custo de setup estavam desalinhados (tabela larga demais); agora tudo em colunas limpas.
💰 Orçamento Inteligente — Fase 1: Configurações do Orçamento. Nova aba ⚙️ Config. Orçamento (onde eram as Compensações) pra definir de uma vez: fiscal (IPI/ICMS/PIS/COFINS), comercial (validade, margem, frete, condição de pagamento), faixas de desconto do kg (por quantidade e por peso) e custo de setup. Validade padrão do orçamento agora é 20 dias. Nada do orçamento atual muda — é tudo acréscimo, salvo junto das ondas sem perder nada.
🌙 Acabamento começa hoje e termina amanhã. Quando o acabamento não cabe inteiro no dia, a máquina (coladeira/grampeadeira) começa hoje — assim que o corte libera os primeiros paletes — e só o resto passa pro dia seguinte. Antes o acabamento inteiro sumia de hoje e rolava pra amanhã, deixando a máquina parada à toa.
🖨 Imprimir / PDF do cronograma voltou. No topo do cronograma tem os botões 🖨 Dia e 📅 Semana — geram uma folha limpa (A4, preto no branco) por máquina, com os 2 turnos, pra imprimir ou salvar em PDF. Antes esses botões ficavam presos no popup do dia antigo, que o cronograma novo não abre mais.
🔍 Botão "Ampliar" no cronograma. Agora tem o botão ⤢ Ampliar no topo do cronograma — clica e ele abre grande no meio da tela, pra visualizar o programa completo sem aperto. Clica em ⤡ Reduzir (ou no fundo escuro / Esc) pra voltar.
🕑 Cronograma agora mostra os 2 TURNOS. A linha do tempo ia só até o fim do 1º turno; agora mostra o 1º e o 2º turno, com o intervalo entre eles e o almoço de cada turno — cabe o dobro de produção no dia.
🔄 Segue o modelo de turno — se você trocar entre horário normal e 12 horas (ou mudar as horas), o cronograma acompanha sozinho.
🌙 Contas da madrugada certas — quando o 2º turno vira a noite, o atraso e o tempo real do operador agora batem certo (sem "parado há 24h").
🔧 Ajustes no Cronograma Inteligente. Clicar num pedido do cronograma agora abre o pedido certo (não abre mais "Novo Pedido" em branco).
⏳ Não congela cedo demais — o plano do dia só é ancorado depois que o cadastro de caixas carrega, pra não travar o dia com a velocidade errada.
✂️ Caixas cortadas por fatia — quando um pedido já cortado é dividido, cada parte mostra a sua quantidade (não repete o total).
🔁 Reprogramado entra na frente — o pedido que sobrou pra terminar agora vai pro início da fila (logo após o que já está na máquina), pra fechar o que ficou pela metade.
🏭 CRONOGRAMA INTELIGENTE — agora por MÁQUINA. O cronograma da Carteira deixou de ser "um bolo de horas por dia" e virou 4 faixas em paralelo: Slotter, Corte e Vinco, Coladeira e Grampeadeira — cada uma com a capacidade dela (7h48).
⚡ Velocidade certa de cada máquina — o tempo de cada etapa sai da velocidade cadastrada na caixa (Slotter / C&V / Coladeira / Grampeadeira). Caixa que corta rápido e cola devagar agora aparece assim no cronograma.
✂️ Cada pedido tem 2 blocos — corte e acabamento, rodando em paralelo (o acabamento entra 30min depois, palete a palete).
◐ PARCIAL — corte pronto e acabamento não: o pedido aparece como parcial, com as caixas cortadas esperando.
🌙 Virada por etapa — se o acabamento não cabe hoje, só a fila daquela máquina rola pra amanhã. O corte já está feito e não repete.
⚓ Horário ancorado — o plano do dia é congelado. Dar baixa não puxa mais os outros pras 05:00: o horário planejado fica de pé e vira a base de comparação com o real.
🛑 Paradas por etapa — o tempo parado do operador acumula em cada máquina e desloca a projeção do fim.
🔁 Zerar a chapa do reprogramado agora vale em TODOS os caminhos — além do dropdown (v2.34.68), agora também quando o operador pede pra reprogramar e você aceita, e quando você usa "Continuar o mesmo pedido". Em todos, a chapa some pra você lançar a chapa nova do que falta.
🔁 Reprogramado zera a chapa — quando você põe um pedido como Reprogramado, a quantidade de chapa some pra você lançar a chapa nova (a do que falta). Só depois que você lançar a chapa nova ele volta pro operador — que já produz o que falta no mesmo pedido (isso já funcionava).
📅 Filtro de data personalizada — no filtro de data da produção, tem a opção "Personalizada": escolhe uma data de e até e a lista mostra só os pedidos com entrega nesse intervalo. Dá pra deixar só o "de" (a partir de) ou só o "até".
🔄 Reiniciar aparece pra pedido "sujo" — o botão "Reiniciar" agora também aparece quando o pedido tem etapa iniciada/concluída, produção lançada ou trava de operador, mesmo com status estranho (ex: "esperando programação" mas com Slotter ✓ e "rodando na grampeadeira" há dias). E o Reiniciar agora solta a trava do operador junto (antes o pedido continuava "rodando" zerado). Era o caso do FK GRUPO travado.
🔄 Troca de turno libera o pedido — no operador, marcar "Troca de turno" agora solta o pedido pro próximo operador continuar (a produção parcial fica creditada), em vez de deixar preso. E na central, o botão 🔓 de destravar volta a aparecer mesmo quando as chaves da trava estavam dessincronizadas (a chave por etapa continuava travada mas o cadeado sumia) — era o caso do KININO 42 preso no João.
🧮 Espelho conta como caixa — na paletização do operador, os espelhos agora entram na soma total (10.805 + 10 espelhos = 10.815 caixas) e no "faltam/sobram". Antes o espelho não contava e dava um "faltam" falso. Agora mostra o total certo, "(N espelhos incl.)" e, se os paletes passarem do que a máquina produziu, avisa "sobram Xcx".
🗑️ Remover palete confirmado (que sobrou) — no operador, o botão "➖ palete" agora deixa remover o último palete mesmo confirmado, com uma pergunta. Antes, se você editava um palete e sobrava um palete de 1 caixa (desnecessário), não tinha como apagar porque estava confirmado.
📄 Caixa com espelho (+1 por palete) — no cadastro da caixa tem um botão "Caixa com espelho"; quando ligado, cada palete leva 1 caixa-amostra a mais (o palete de 1000 vira 1001). No operador tem o botão "📄 espelho: sim/não" na paletização (já vem do cadastro, dá pra mudar no pedido), mostra "+1 espelho" em cada palete e o total de espelhos, e a etiqueta impressa já sai com a conta certa (1.001, "1000 + 1 espelho"). Também consertei o botão 🌀 Caracol que não ficava salvo ao reabrir a caixa.
🌀 Amarração em caracol (cata-vento) na paletização — 4 caixas girando em volta do centro, com a camada par girada 90° (trava de verdade, as emendas nunca se repetem). O sistema escolhe sozinho quando vale a pena: caixa "quadradona" (comprimento até ~2× a largura) e o caracol empata ou ganha em caixas na base. Também dá pra forçar no botão "🌀 Caracol" na orientação da caixa. Caixa comprida e fina segue na amarração normal.
📦 Paletização desenha sozinha — no cadastro da caixa, se você não informar o palete, o sistema assume o padrão PBR 1000×1200 e já desenha (não precisa mais preencher o campo do palete pra ver). E quando não dá pra desenhar, no lugar do vago "Preencha as medidas" agora aparece o motivo exato: ex. "a caixa dobrada 1075×1331mm não coube no palete 1000×1200 — informe um palete maior ou gire a caixa".
🪪 Busca da Vida da caixa na Curva ABC — agora é só digitar o código da caixa (ex: 33) ou o cliente lá na Curva ABC e abre a vida da caixa: todos os pedidos que aquela caixa já produziu, com o processo de cada um. E o RG passou a abrir qualquer pedido (busca direto no banco, mesmo pedido antigo/entregue que não está carregado). Corrigido também: Corte e Vinco agora aparece na etapa "Slotter/Corte" do RG (antes sumia).
🚚 Vida da caixa também na Expedição — no Histórico de Cargas, o 👁 agora abre os pedidos daquela carga e cada um tem o botão "🪪 Vida da caixa" (a 3ª porta de entrada do RG). De quebra, o 👁 que antes não fazia nada passou a funcionar.
🪪 NOVO: Vida da caixa (RG) — o histórico COMPLETO de um pedido, do lançamento à entrega, num cartão só: cabeçalho (Sectra, cliente, medida, cores), alterações, onduladeira (chapas + kg estimado), Slotter e Coladeira (qtd, perdas), ocorrências agrupadas por etapa com FOTO e descrição, paletes, expedição (quem carregou) e entrega. Abre pelo botão "🪪 Vida da caixa" dentro do pedido e no cadastro de Caixas. Os buracos (motorista, kg real) aparecem marcados como "aguardando integração". Só leitura.
📉 Perdas somam pra achar a caixa boa — no operador, as ocorrências de chapa (bolada, úmida...) agora entram na conta junto com as perdas de ajuste e produção. Ao finalizar, o card mostra ao vivo: total − ocorrências − ajuste − produção = caixas boas que vão pra Coladeira/Grampeadeira (ex: 5.000 − 30 = 4.970). Cada máquina desconta só as ocorrências dela. Só acréscimo — a qtd que vai pra próxima etapa já sai certa.
📦 Paletização + relógio de produção — nas imagens do palete, o desenho agora fica centralizado e cada pacote ganhou borda destacada (dá pra ver caixa por caixa). No operador, ao iniciar a produção o card vira um relógio gigante (modo foco) dominando a tela. E se o operador pular a paletização sem querer, agora aparece o botão "📦 Configurar paletização" pra voltar (antes travava sem volta) — o Pular também passou a pedir confirmação.
📦 NOVO: Paletização automática — no cadastro da caixa (seção 8), o sistema calcula o lastro sozinho (amarração > colunar) puxando a chapa da seção 5, e desenha 3 imagens do palete: vista de cima, 1ª camada e palete completo (pacotes kraft, fitas de arquear, camadas alternadas 180°). Controles: orientação (auto/normal/invertida), amarração entre camadas, palete fora do padrão. Mostra caixas por palete + paletes do pedido + regra do caminhão. O operador de Coladeira/Grampeadeira vê as 3 imagens + tudo no app, com a quantidade vinda da produção real da Slotter. A imagem manual antiga continua como opção. Nada se perde em caixa antiga. (frontend puro — sem Luan)
🔓 Conserto: destravar pedido não destravava no operador. Quando dois operadores entravam no mesmo pedido (ex: coladeira) e você liberava a trava na central, não soltava em ninguém. Motivo: a trava do operador é por etapa (chave pedido__coladeira) mas o destravar gravava só na chave antiga. Agora libera todas as etapas travadas daquele pedido de uma vez — solta no operador de verdade.
🏷️ Etiqueta de clichê/faca: número no formato 124-B (número-letra), CL/FC em cima, bem maior (~20mm), em Arial Bold (mais nítido na térmica). O número vem do campo do cadastro quando preenchido.
🏷️ Ajustes na etiqueta de clichê/faca (pedido do chão): número do clichê bem maior e centralizado, tirado o "JP EMBALAGENS" e o "1/2" grande do meio (o "· 1/2" fica no topo) — tudo pra sobrar espaço pro número. E o mais importante: o número agora vem do campo "Nº do Clichê" do cadastro da caixa (se você preencheu 124, sai CL-B124); só quando o campo está vazio é que o gerador cria automático. Etiqueta continua 75mm × 100mm.
🏷️ NOVO: Gerador de Etiquetas (Clichê & Faca) — nova tela na aba Produção. Gera etiqueta térmica 75×100mm (preto-e-branco) pra clichê e faca, puxando os dados direto do cadastro da caixa (cliente, referência, medida, cores). Numeração automática: contador geral (CL-{máquina}{nº}, FC-{máquina}{nº}). Cadastro de máquinas editável (A/B/C e as que quiser — cada uma diz se gera faca); o campo Máquina entrou no cadastro de caixa. Caixa nova com máquina já ganha número sozinha; caixa antiga você numera uma vez pelo botão. Uma etiqueta por cor (contador 1/3, 2/3…), + Etiqueta avulsa e busca por número (acha "CL-A241", "cla241" ou "241"). Tudo frontend — funciona já no push. O contador 100% à prova de dois usuários ao mesmo tempo é um upgrade opcional (doc do Luan).
📱 Conserto: caixas/clientes sumindo no iPad/celular. No iPad o pedido não achava a caixa ("cadastre primeiro uma caixa") e não mostrava a medida da chapa — porque o navegador (Safari) limpava o cache das caixas (são grandes por causa das imagens) e o sistema, por causa de um carimbo, não recarregava do servidor. Agora lista local vazia SEMPRE recarrega do servidor (vale pra caixas, clientes, papéis, cores, chapas e operadores). No PC já funcionava; agora no iPad/celular também.
🔄 Reabrir pedido PRONTO (produzir de novo): agora dá pra Reiniciar um pedido já finalizado — o botão aparece no "pronto" também. O problema antigo era que o operador continuava com ele marcado como "concluído" e o sistema re-marcava pronto em poucos segundos (PCP e operador puxando pra lados opostos). Agora, quando você reabre, o pedido ganha um carimbo de reabertura: tanto o PCP quanto o operador passam a ignorar qualquer "concluído" mais antigo que a reabertura (não apaga nada — só desconsidera o velho). O pedido volta pra material disponível e o operador o vê pra produzir de novo; só o que ele produzir depois da reabertura conta. (precisa o Luan reiniciar a API pra valer)
📌 O status que você põe na mão GRUDA — não volta mais: aquele problema de "tiro programado, ponho esperando programação e ele volta pra programado sozinho" acabou. Agora vale a regra "a última edição na mão vence" (não mais "o status mais adiantado vence"). Achamos 3 portas por onde ele voltava e fechamos todas: (1) a importação do relatório não recrava mais por cima do status que você decidiu na mão — ela atualiza cliente/código/quantidade/data, mas respeita o status que você pôs; (2) a sincronização entre aparelhos passou a respeitar a edição mais recente em qualquer direção (dá pra baixar de propósito, não só avançar); (3) a tela de Programação passou a carimbar a decisão pra ela não voltar por sync/importação atrasada; e (4) a janela "Editar" (lápis) também passou a carimbar a mudança de status — antes por ali o status ainda voltava. Quem nunca foi mexido na mão continua seguindo o relatório normalmente.
🧱 "Material disponível" agora EXIGE chapa: um pedido só fica material disponível (liberado pro operador) se tiver chapa lançada. Se você zerar a chapa na mão, ele volta um status (vira programado). E o sistema corrige sozinho os pedidos que estavam "material disponível sem chapa" (voltam pra programado) — era o que fazia a central mostrar 0 material disponível enquanto o pedido aparecia como material no cronograma. Agora os dois batem. (precisa o Luan reiniciar a API pra valer nos 2 aparelhos)
🔁 Reprogramado no cronograma + só libera com chapa: o reprogramado voltou pro cronograma (o operador tem que ver o que vem). Mas ele só é liberado pro operador produzir quando tem chapa lançada (aí é como material disponível); sem chapa fica no PCP/cronograma esperando você reprogramar — o operador não recebe o que não dá pra produzir. O "continuar mesmo pedido" (que mantém a chapa) segue indo direto pro operador.
💵 Fila de Baixa (faturamento): tela nova em Expedição → Baixa. Lista os pedidos que saíram e ainda não foram faturados, com número + quantidade prontos pra digitar no Sectra. Clica "Dei baixa" e o pedido sai da carteira ativa e vai pro histórico (com tudo: produção, quem fez, ocorrências) — não mexe no "entregue" do motorista. Se saiu menos que o pedido, pergunta: baixa total (cliente aceitou) ou reprograma o resto (reabre o que falta pra produzir). É só do nosso lado — quando o fornecedor do Sectra liberar escrever por fora, plugamos o envio automático.
🚚 Fim do "expedi e volta" + estoque limpo: (1) o estoque PA para de mostrar pedido já carregado/entregue (não é produção pendente) e o botão "Expedir" do estoque agora marca o pedido como Carregado — assim a caixa não volta mais. (2) botão novo "🔤 Unificar nomes" no estoque: normaliza o nome do cliente dos pedidos pro do cadastro (ex.: "FK GRUPO" → "FK Grupo"), acabando com estoque/relatório/ABC duplicado por diferença de nome.
💰 O painel de Custos ("vendido no mês") passa a contar o faturado (da Fila de Baixa), não só o "entregue" — reflete a venda de verdade (às vezes fatura e o cliente pede pra esperar a entrega).
🛡️ Blindagem da importação — fim do "pedido some": a Importar Relatório era a única porta sem trava (apagava a carteira inteira e regravava a foto, às vezes atrasada, da central). Agora ela não derruba mais quem já está andando: pedido que o operador pegou não some, excluído não volta, e produção, entregues e o rastreio de estágios/programação não são apagados por um import com foto velha. A caixa que saiu do relatório só sai se for planejamento — histórico nunca some. Precisa do restart do servidor (Luan) pra valer.
👤 Fim do cliente fantasma: a importação agora casa o cliente do relatório com o cadastro e grava o nome real (ex.: "DEUSA ALIMENTOS" no lugar de "Deusa") — assim a caixa, o endereço e a análise ABC deixam de tratar o mesmo cliente como dois. No fim da importação aparece a lista de clientes sem cadastro pra você cadastrar. E o pedido lançado na mão não duplica mais com a mesma venda que vem no relatório (ele reconhece que é o mesmo pedido e junta, em vez de criar um 2º cartão).
🏭 Operador não atropela mais a lista (fim da "briga de quem grava por último"): quando o operador libera parcial, finaliza uma etapa ou registra perda, ele não regrava mais a lista inteira em cima do que o PCP publicou — cada coisa vai pro seu lugar sem colidir. Isso fecha o último buraco de pedido sumir/voltar da tela do operador quando o PCP publica no mesmo instante. (Recomendado testar com 2 aparelhos no chão antes de confiar 100%.)
📦 Caixa em estoque na linha do pedido (PCP + Programação): quando o pedido tem caixa pronta no estoque, aparece abaixo da linha de produção um alerta amarelo "📦 X cx dessa caixa em estoque". No PCP tem também o total no rodapé. E o estoque fantasma sumiu: o que já foi expedido (carregado/entregue) não conta mais no alerta — antes mostrava caixa que já tinha ido embora. Não apaga nada do estoque, só para de contar o que já saiu.
🔒 Turno obrigatório + bloqueio por aparelho: em Análises → 🔐 Acessos, dois interruptores que você liga quando quiser — "Exigir turno" (quem não tem turno cadastrado não entra) e "Só aparelho autorizado entra". Embaixo, a lista de aparelhos: dá pra dar um nome, autorizar os tablets da empresa e bloquear o resto (pelo id do aparelho — o navegador não deixa ler o MAC). Tudo desligado por padrão e à prova de glitch (se a rede cair na hora do login, não trava a fábrica).
📢 Recado pro operador + turno na lista: no cadastro do operador tem um campo de recado personalizado — quando ele entra, aparece um aviso grande na tela dele (ex: "priorize o pedido da Deusa · confira a faca"). E a lista de operadores agora mostra o turno de cada um (ou "sem turno") e um selo 📢 quando tem recado. O campo de apelido saiu da tela de login (o operador entra pelo nome).
🔐 Turno + log de acessos do operador: no cadastro do operador dá pra definir o horário que ele pode entrar (hora início/fim + dias da semana; vazio = entra sempre; turno que vira a noite funciona). Fora do horário, o app não deixa entrar e registra a tentativa. E toda entrada fica num log na central (Análises → 🔐 Acessos): quem entrou, quando, em qual aparelho (detecta iPhone/Android/PC + o apelido que você dá pra cada tablet) e as tentativas bloqueadas.
🔗 "Deusa" agora vincula com "DEUSA ALIMENTOS": o pedido entra com o apelido curto e as caixas estão cadastradas com o nome completo — o vínculo caixa↔pedido exigia nome idêntico e não achava nada. Agora, se o exato não achar, aceita 1ª palavra do cliente igual + candidata única (Deusa ↔ DEUSA ALIMENTOS casa; Alpack ↔ Deusa continua impossível; ambíguo não vincula). Vale pra importação (medidas/preço/ficha) e pra programação/laudo. Reimporte o relatório no modo Atualizar pra vincular os pedidos de hoje.
🏷️ Caixa da Alpack não entra mais como Deusa: o apelido do cliente na importação casava por "contém a 1ª palavra" — e "INDUSTRIA" (do nome fiscal da Deusa) casava com qualquer cliente que tivesse INDUSTRIA no nome (a ALPACK caiu nessa em 03/07). Agora só casa 1ª palavra IGUAL e palavra genérica (INDUSTRIA, COMERCIO…) não identifica ninguém. + Alpack cadastrada com apelido próprio. Pra corrigir os 2 pedidos de hoje: reimporte o relatório no modo Atualizar — eles viram Alpack sozinhos.
🛡️ Chapa não some mais + operador pegou = EM PRODUÇÃO: dois consertos definitivos no caso 23393/01.02. (1) A chapa lançada era revertida pelo servidor atrasado depois de 90 segundos — agora a proteção compara carimbos de edição (a tua edição só cede quando o servidor comprovadamente a conheceu), então a chapa não desaparece mais e o status não volta sozinho. (2) Quando qualquer máquina pega o pedido (Slotter, coladeira…), o status vira EM PRODUÇÃO na hora — antes só mudava quando a etapa concluía, e ficava "material disponível" com a máquina rodando.
⚖️ Média de preço por QUILO (R$/kg): a régua justa pra comparar caixa grande com pequena — faturamento ÷ quilos entregues (qtd × peso da caixa do cadastro). Aparece em 3 lugares: coluna R$/kg por cliente no Clientes ABC (+ média geral no rodapé), coluna R$/kg por caixa na lista de caixas do cliente (+ média do cliente no resumo), e na Vida da Caixa (faturado, quilos entregues e média R$/kg — ex: 31644 = ~240 toneladas). Caixa sem peso no cadastro mostra "—" (cadastre o peso pra entrar na conta).
📦 Vida da Caixa reorganizada: agora é cliente → caixa → tabela de pedidos (nº, lançado em, entregue, em aberto, R$/cx) com o gráfico mensal embaixo — e clicou no pedido, abre a produção dele: quem rodou, em qual máquina, dia a dia, e tudo que aconteceu (mesmo quando passou por 2 máquinas — Slotter + grampeadeira — fica tudo junto no pedido). Pedido antigo mostra só o lado comercial, marcado "antes do sistema".
📦 Vida da Caixa no Clientes ABC: dentro do cliente, agora clica na caixa e abre a vida dela — o lado comercial do Sectra (entregas desde o início, por ano, preço e como mudou, parcelas em aberto — alimentado pelo espelhamento automático) e o lado fábrica (produções com dia/quantidade/operador/máquina + eventos da vida dos pedidos). Teste já ativado com a caixa 31644 da Frisokar (117.634 cx entregues desde out/2024).
📜 Vida do pedido: cada pedido agora tem a sua linha do tempo — quando nasceu (importação, na mão ou orçamento), programado pelo PCP, chapa lançada/produzida, começou a produzir (com operador e máquina), ficou pronto, etiquetas impressas, mudanças de data (🔁 reprogramação do relatório), edições (o que mudou, de → para), reinícios, status trocado na mão… tudo com data, hora e quem fez. Aparece no fim do modal de editar o pedido, seção "📜 Vida do pedido" (mais novo em cima). Os eventos começam a ser gravados a partir de agora.
🔁 Importar relatório: mudança de data NÃO duplica mais o pedido: quando o cliente muda a data de entrega no Sectra e o relatório é reimportado, o sistema agora entende que é o mesmo pedido reprogramado — atualiza a data e mantém a produção, o laudo e tudo. Entregas parceladas (mesmo pedido com várias datas de propósito) continuam funcionando como antes. Só pareia quando é inequívoco: na dúvida (2 datas mudadas de uma vez, pedido já produzido/entregue, linha sem data), mantém o comportamento antigo pra nunca perder pedido. + blindagem anti-colisão de id pra parcela nova na data antiga nunca ser engolida.
🏷️ Etiqueta de bobina toda preta e maior: pra impressora térmica de ribbon (monocromática), a etiqueta agora é tudo em preto (nada de cor virando cinza), com o nome do cliente bem maior, o lote / NF / data maiores e em negrito no rodapé, e o espaço melhor aproveitado (QR maior). Vale pra imprimir e reimprimir.
💰 Preço do almoxarifado só na central: no app do almoxarife o preço saiu da tela (é dado de gestão) — mas continua sendo gravado normalmente. Aqui na aba Estoque do Almoxarifado chegou a coluna Preço/un editável (você digita e salva na hora), a coluna Valor (saldo × preço) por peça e o total R$ em estoque no topo. Preço e códigos de barra continuam no mesmo lugar, então app e central ficam sincronizados.
📦 App Almoxarifado reformado (Estoque · Entrada · Saída): a aba Estoque agora mostra preço, R$ em estoque e a prateleira·seção (🗄️) de cada item. A Entrada virou carrinho — bipe vários produtos (leitor USB ou câmera), ajuste/apague, e finalize tudo de uma vez gerando todas as etiquetas juntas (QR + código + nome + data) já mandando pra impressão. Cadastro de produto novo com preço/prateleira, vincular outra marca ao mesmo produto e gerar código interno. A Saída pede obrigatoriamente quem retirou + setor. Preço e códigos de barra guardados por peça (frontend, sem depender do backend).
🏷️ Reimprimir VÁRIAS etiquetas de uma vez: na tela de reimprimir do app Qualidade, agora dá pra marcar quantas bobinas quiser (checkbox), com "Marcar todas" e busca por código/dono — o botão mostra quantas vão sair (ex: "Imprimir (5)") e imprime todas juntas na Elgin 100×75.
🏷️ Etiqueta de bobina 100×75mm + reimprimir: a etiqueta agora sai no tamanho 100×75mm deitada (impressora térmica Elgin) — QR na esquerda, código e dados na direita. E no app Qualidade tem um botão "Reimprimir etiqueta de bobina": procura pelo código ou dono e imprime de novo, quando quiser.
🛒 App de Compras voltou a abrir: a lista de compradores tinha ficado com o dado "embrulhado em dobro" e travava o login em "Carregando…". Corrigi o dado (na hora, sem perder ninguém) e blindei os apps de Compras, Almoxarifado e o cadastro central pra nunca mais travar por isso.
🎨 Cor com quadradinho + qtd do pedido no laudo: no app Qualidade, a cor da caixa agora mostra o quadrado colorido ao lado do nome (ex: 🟩 VERDE ESCURO DH 06 · ⬛ PRETO). E a Qtd pedido, que aparecia "0 cx" no detalhe, voltou a puxar a quantidade certa.
🧻 Recebimento de bobinas: largura, rolos e tela pro computador: ao importar a NF (XML), a largura (ex: 1400 mm) e a gramatura vêm preenchidas por rolo, e a quantidade de rolos de cada item vem certa do próprio lote da nota (ex: 14 / 11 / 9 — antes estimava pelo peso e dava 17). No computador, cada rolo virou uma linha só com as colunas alinhadas, bem melhor pra digitar; no celular continua empilhado.
🧻 Gramatura da bobina pré-carregada no recebimento (XML): no app Qualidade, ao importar a NF de bobinas, a gramatura passou a aparecer num campo próprio por rolo, já preenchida da nota.
🏷️ Dados da caixa no app Qualidade: o PCP agora manda pro laudo a cor, as medidas internas (L×A×C), onda, coluna, gramatura e a quantidade de paletes de cada pedido. Antes o app Qualidade não enxergava esses campos — agora aparecem na tela de detalhe e no PDF do laudo.
👤 Dono padrão no recebimento de bobinas (XML): no app Qualidade, ao importar a NF de bobinas, tem um campo "Dono padrão" no topo — escolhe uma vez e preenche o dono de todas as bobinas, e fica lembrado pra próxima. Só troca uma por uma se precisar.
🎞️ Bobina: código segue o dono — ao transferir uma bobina pra outro dono, a etiqueta/código agora é regerado com o prefixo do novo dono (ex: JP-BOB-0025 → DCXPACKAGING-BOB-0004) e o app avisa pra reimprimir. (A parte do servidor precisa do deploy do Luan pra valer.)
🔬 No painel de apps (QR), o app "Laudo" agora se chama "Qualidade".
🩹 Fix: 📔 Diário não aparecia no menu — faltava liberar a tela nas permissões dos perfis (estava escondida pra todos, até admin). Agora aparece em Análises. (A Rastreabilidade tinha o mesmo problema e também voltou.)
🏭 Diário por máquina: no Diário, além de "por operador", dá pra ver "por máquina" — escolhe a máquina e o dia e vê quem operou e tudo que rodou nela (pedidos, perdas, paradas, ocorrências), com as mesmas horas e média.
⏱️ Diário do Operador — horas e média: o Diário agora mostra também as horas trabalhadas, horas em produção, horas de ajuste, e a média de caixas por hora (cx/h) do operador no dia.
📔 Diário do Operador: na aba Análises → Diário, escolhe o operador e o dia e vê a linha do tempo completa — do bater ponto ao fim do turno, com cada pedido (cliente, qtd, perdas), ajustes, ocorrências, paradas e os vãos entre pedidos. Tudo do dia num lugar só.
⚙️ Mapa de Perdas por setor: na aba Análises → Perdas, novo painel que mostra as perdas agrupadas por setor responsável (produção = máquina do operador; ocorrência = setor da chapa). As ocorrências agora entram no total de perdas. Vê de uma vez quem mais perde: onduladeira, slotter, coladeira, grampeadeira, corte e vinco.
🛡️ Trava anti-apagão: nenhuma tela consegue mais salvar uma lista vazia por cima de uma lista cheia no servidor (foi o que zerou a manutenção — já recuperada do backup). ⚙️ Setor responsável pela perda na ocorrência (Onduladeira/Slotter/Coladeira/Grampeadeira/Corte e Vinco) + ranking de perdas por setor na central (igual ao por fornecedor).
🔧 Correções da auditoria (trilha B): guardas anti-tela-branca (÷ por zero no cronograma, dados faltando em etiqueta/viagem/caixa, popup do laudo, palete sem id) · proteção XSS/aspas em botões e banners · WhatsApp do DDD 55 (RS) agora leva o país certo · login do expedidor (número×texto) · laudo fecha como “Laudado” mesmo com produção 0 · filtro das comissões. (Itens de backend/segurança foram pro time do servidor.)
🛠️ Correções da auditoria de código (trilha A): importação não cruza mais caixa de outro cliente · app Qualidade volta a apitar pedido novo na fila · scanner do almoxarifado bipa várias peças sem fechar a câmera · histórico de cargas não quebra com dado faltando · expedição detecta o motorista voltando · meta de produtividade corrigida · index.html agora encaminha pro sistema · + guardas anti-tela-branca.
🔒 Status SEGURA agora (Reprogramado etc.): mudar o status no PCP não sincronizava (mesmo bug da chapa) — voltava no próximo sync. Agora SINCRONIZA na hora, o import não força mais “em produção” num reprogramado, e o export atrasado não reverte. + chapa protegida do dado atrasado.
🐛🔥 CAUSA RAIZ do pedido sumindo: ao programar a qtd de chapas no PCP, o sistema salvava SÓ LOCAL e não mandava pro servidor — aí no próximo sync voltava “chapas 0” e o pedido sumia de “material disponível”. Agora a chapa SINCRONIZA na hora. Resolve KININO 22, 01.02, 31644 e qualquer pedido que sumia depois de programar.
👥 Crédito do parcial por operador: ao finalizar o turno com pedido pela metade, a produção do operador é gravada no registro DELE (sem concluir a etapa), e o próximo operador continua e leva o crédito do que ELE fizer. Cada um com sua produtividade real. Precisa teste com 2 operadores.
🏁 Resumo do turno completo: o resumo de fim de turno do operador agora inclui os pedidos EM ANDAMENTO (parcial) — caixas e ajustes — além dos concluídos. Não some mais o que ele fez num pedido que não terminou.
🐛 Fix do filtro/contadores: filtro “material disponível” e os cards (contadores) agora usam o status EFETIVO — pedido material disponível SEM chapa não aparece mais nesse filtro (vai pro “esperando programação”, certo).
✅ Material disponível só com chapa: pedido marcado “material disponível” MAS sem número de chapa agora aparece como “esperando programação” e NÃO vai pro operador (resolve o pedido que voltava sem chapa, ex: DEUSA 01.02).
✍️ Registrar Produção — máquina e operador da lista: no modal de registrar produção, os campos Máquina e Operador agora sugerem os cadastrados (datalist) — escolhe da lista ou digita.
📊 Barra do reprogramado certa: pedido reprogramado mostra o progresso do PEDIDO TODO (ex: fez 1065 de 3000 → falta 1935, 36%%), não da chapa do turno. E a publicação pro operador ignora registro cancelado (anulado).
🔁 Reprogramado agora aparece no operador: pedido REPROGRAMADO volta pra produzir no app do operador (em TODAS as máquinas, mesmo já concluído), mostrando o que falta (ex: 1065 feito → falta 1935). Corrige o caso do 31644.
🔄 Operador — Reprogramar e Reabrir: no aviso de produção incompleta agora tem Reprogramar (manda pro PCP), e no pedido concluído tem Reabrir. O pedido (mesmo nú) volta pra “A Programar” como Reprogramado e o operador produz o resto somando. Canal aditivo novo (não mexe no sync existente). Precisa teste real com pedido TESTE_.
🔁 Produção parcial — Continuar MESMO pedido: no modal de decisão do PCP (quando o operador finaliza com menos), além de Aceitar Parcial e Reprogramar Diferença (pedido novo), agora tem Continuar MESMO pedido — o mesmo nú volta como Reprogramado, mantém a meta, e o operador produz o resto somando, até completar.
📊 Almoxarifado — Relatório de saída: nova aba que mostra o que saiu, pra quem, data/hora e quantidade, com filtro por período e busca, mais Imprimir e Exportar CSV. + corrigidos 3 detalhes da bipagem (trocar de peça sem finalizar agora pergunta; código bipado sempre acha a peça; câmera não dispara durante o cadastro).
📠 Almoxarifado — Entrada por bipagem: bipa o código de barra de fábrica; se a peça não existe abre o cadastro com o código já preenchido; cada bip do mesmo código SOMA 1 (ou digita a quantidade no +/−), e no fim gera N etiquetas. Câmera em modo contínuo (bipa várias sem fechar).
🏷️ Peças — código de ENTRADA + código de SAÍDA: cada peça agora tem 2 códigos. ENTRADA = o de fábrica (opcional; sem ele a entrada é manual). SAÍDA = gerado automático e único (S-0001, S-0002…), nunca repete — vai na etiqueta/QR e é o que se escaneia na aba Saída do app do Almoxarifado pra dar baixa da peça. Resolve a etiqueta que saía com “—”. Peças antigas ganham o código sozinhas (backfill). Vale no Sistema e no app do Almoxarifado.
📦 Almoxarifado — cadastrar peça no app: na Entrada, quando a peça não existe, “➕ Cadastrar nova peça” cria no catálogo (mesmo /api/pecas do Sistema) e já seleciona pra dar entrada. Botão também no Estoque. · 🧾 Compras — compra avulsa: botão pra criar compra direto, sem solicitação (cai em Solicitadas com selo 🛒 Avulsa).
📦 Encarregado — Requisição de peça: botão + aba pra pedir peça do estoque do almoxarifado (escolhe do catálogo → o almoxarife entrega/compra). Fecha o ciclo encarregado ↔ almoxarife. (+ corrige o nome “[object Object]” nos cards.)
✅ CORRIGIDO o login do Almoxarifado: faltava a linha que cria o db (firebase.firestore() do shim) — por isso o login dava “Can’t find variable: db” e ficava vazio. Agora os nomes aparecem.
🔬 Diagnóstico no login do Almoxarifado: se a lista vier vazia, mostra na tela o que o servidor respondeu (pra achar a causa do login vazio).
🔑 Login do Almoxarifado: timeout de carregamento subiu p/ 20s (a 1ª conexão da hospedagem demora) + botão “Tentar de novo”. Resolve o login que aparecia vazio mesmo com gente cadastrada.
🔑 Cadastro de Comprador com Acesso: no cadastro você escolhe se a pessoa loga em Compras, Almoxarife ou nos dois (um cadastro p/ 2 apps). E o login do Almoxarifado ficou à prova de falha (não trava mais em “Carregando”).
🛒 Compras — lista item por item: solicitação com vários itens grudados numa linha agora aparece separada (igual a Manutenção), com a contagem certa, na lista, no PDF e na mensagem da OC.
📋 Almoxarifado — Requisições (Fase 3): nova aba onde se cria a requisição de peça e o almoxarife atende (entrega do estoque / manda pro compras), reusando /api/solicitacoes. (+ corrige um bug que travava a troca de abas.)
🔫 Almoxarifado — leitor de código de barras (Fase 2): o scanner agora lê QR e código de barras de fábrica (EAN/Code128…). Código novo? Você vincula a uma peça uma vez e depois ele reconhece sozinho — na saída e na entrada.
🔑 Login do Almoxarifado: agora aceita TODO mundo cadastrado com senha (compradores, manutenção, encarregados, operadores, expedição), juntando as listas e tirando repetidos. Antes só comprador entrava.
🧻 Receber bobinas sem reimportar a NF (Qualidade): ao importar a NF (kg), aparece “Receber as bobinas dessa NF” → vai direto pra conferência do romaneio (rolo a rolo), já com o papel/dono preenchidos. Não precisa mais importar o XML duas vezes.
📦 Novo app: Almoxarifado — estoque de peças por categoria (KPIs, alerta de mínimo), entrada gerando etiqueta com QR (1 por caixa ou N por unidade), e saída lendo o QR. Login por PIN. (Backend já estava no ar.)
🔎 Rastreabilidade da bobina (Bloco 5): nova aba em Análises com a vida inteira de cada bobina (entrou → saiu → consumida → caixa), por bobina ou por pedido. (depende do Luan rodar a migration 020.)
📱 Ícone JP padrão em todos os apps: ao instalar na tela inicial, todo app abre o SEU painel com a logo da JP (Android e iPhone). Corrigido também o ícone do iPhone que estava quebrado.
🧻 Onduladeira — consumo de bobina (Bloco 4): no lançamento, lê o QR/código das bobinas (capa/miolo/contracapa), confronta gramatura/largura e desconta os metros (miolo ×1,35) → sobra vira 🪵 toco, acaba vira ⬛ consumida.
📱 App na tela inicial corrigido: cada app (Operador, Qualidade, Expedição, Motorista, Escala, Vendedor) agora abre o SEU painel ao instalar — antes o ícone caía no sistema.
🔄 Transferir bobina entre depósitos: no app Bobinas, cada bobina disponível ganhou o botão Transferir — muda o dono (terceiro) pra outro depósito ou pra JP. Útil quando o papel de um terceiro vai ser usado por outro.
🧻 Receber bobina — DONO vira lista de terceiros: o campo DONO de cada rolo agora é um dropdown com a JP + os terceiros cadastrados, já pré-selecionado pelo que a NF puxou. Quem lança escolhe pra qual depósito (terceiro) vai cada bobina.
🏷️ Receber bobinas — imprimir TODAS as etiquetas de uma vez: no “Recebimento conferido” (app Qualidade) apareceu um botão Imprimir etiquetas que sai com a etiqueta+QR de cada bobina criada, 1 por página, num print só.
📐 Programação — cards filtram + resumo por onda: clicar em Atrasados ou Esta semana filtra a lista (clicar de novo limpa). E apareceu um resumo 🌊 Por onda (quantos Onda B, Onda BB…) do que está sendo mostrado.
🔧 Manutenção — peças item por item: quando vários componentes vinham amontoados num texto só (separados por vírgula ou “+”), agora a solicitação mostra item por item (no card e no PDF), com a quantidade certa de cada. Só exibição — não muda o dado nem a edição.
🛡️ Senha por email mais segura (revisão): trava de tentativas (anti força-bruta) no login/esqueci/trocar senha, e o link de reset só é guardado se o email realmente sair.
🔑 Trocar senha por email: na tela de login tem "Esqueci a senha" — o sistema manda um link no seu email pra definir uma nova (vale 30 min, uso único). E logado, o 🔑 no topo troca a senha (atual → nova). Depende do Luan subir a migration 019 + configurar o email (Resend).
🔢 Quilo casa por número: no ranking, quando o código do pedido difere do cadastro mas o número bate (ex: KININO 06 ↔ CX 06), o sistema casa sozinho e mostra o quilo. (Só quando é único, pra não errar.)
⏱ Tempo real por caixa: ao clicar no cliente (ranking), cada caixa agora mostra a cx/h real (produtividade do processo final, do início/fim dos registros) — e marca a ⏱ mais rápida do cliente. Pra saber qual caixa rende mais por hora.
🔗 Ranking não divide mais o cliente: o mesmo cliente escrito de jeitos diferentes (ex: "FK GRUPO" e "FK Grupo") virava 2 linhas e atrapalhava o ranking. Agora junta tudo (ignora maiúscula/acento/LTDA) e mostra o nome mais usado. (O FK subiu pro 3º lugar.)
📅 Carteira — filtro de datas pra trás: o filtro de período ganhou as janelas passadas — Último mês, Últimos 2 meses e Este ano (além das de "a entregar"). Junte com o status Entregue pra ver o que saiu em cada período. O "Em atraso" continua mostrando os vencidos.
🛡️ Barreira anti-"volta" (no servidor): o sync de pedidos virou "só avança, nunca volta" — pedido excluído não ressuscita, status não rebaixa (entregue não vira "a fazer") e registro de operador não some. Acaba de raiz o problema de coisas voltando depois de sincronizar.
⭐ Ranking de clientes (curva ABC) com período: filtro de mês atual / 30 dias / este ano / período personalizado (pela data de entrega) — pra ver quem é top em cada janela.
📦 Clique no cliente abre as caixas dele no período, ranqueadas da que mais sai pra que menos sai, com quantidade, preço médio/cx e quilo.
📦 Caixa expedida não volta mais pro estoque: tinha um B.O. — quando a produção sincronizava, caixas que já foram embarcadas (numa carga finalizada) reapareciam no estoque como se estivessem prontas de novo. Agora o estoque cruza com as cargas e não re-adiciona (nem deixa parado) o que já saiu. As caixas-fantasma somem sozinhas. (Foi o caso do 35597 / pedido 23357 da FK.)
🔢 Correção pontual: o registro da grampeadeira do 35597 estava com 4,03 em vez de 4.030 (o ponto de milhar virou vírgula na importação do sistema antigo) — corrigido.
🏗️ Saída de bobina (empilhadeira): no app Bobinas tem uma aba nova Saída / Empilhadeira — lê o QR da bobina (ou digita o código), confere, e dá baixa (vira 🚚 saiu) escolhendo o destino (Onduladeira/Outra) e a posição. Os metros NÃO são descontados aqui (isso é na onduladeira). A entrada/lista/etiqueta continuam iguais. Depende do Luan subir a migration 017 + a rota /saida.
🗑️ Admin original pode excluir chamados e ocorrências: nas telas 🔧 Manutenção e ⚠️ Ocorrências (módulo Análises), apareceu um ✕ Excluir (com confirmação) — só pro admin original (o dono, pelo e-mail). Útil pra limpar testes. Apagar o chamado some também do app de Manutenção. Nenhum outro usuário vê o ✕.
🛒 Compras mostra a lista completa das peças: quando a solicitação tem várias peças, o app de Compras agora lista todas (nome + quantidade + foto clicável) no card, na mensagem de WhatsApp/e-mail (numerada) e no PDF da Ordem de Compra. Solicitações antigas (uma peça) continuam iguais.
📅 Data de entrega no app Operador: nos cards de pedido e de concluído agora aparece o número do pedido + a data de entrega. Resolve a confusão de ter dois pedidos com o mesmo número e mesma caixa mas datas diferentes (ex: um pro dia 19/06 e outro pro 17/07).
✏️ Corrigir produção de um pedido concluído: dá pra arrumar a quantidade lançada errada (ex: 10.000 que era 1.000). No PCP, abre o pedido → "Corrigir produção" (vale até pra pedido já pronto). No app Operador, os concluídos que vinham "só leitura" agora abrem pra corrigir a quantidade. Corrige aqui e no sistema, sem reiniciar nada.
📦 Estoque de caixas — adicionar manual: no estoque dá pra lançar caixas na mão — escolhe o cliente, puxa a caixa cadastrada dele, e informa a quantidade + caixas por palete (sugere sozinho pela paletização da caixa). Entra junto com as que vêm automáticas da produção, sem mexer em nada do que já existe.
🔧 Manutenção — solicitação de peças com VÁRIAS peças: a solicitação de compra agora aceita uma lista de peças (nome + quantidade + 📸 foto por item), com descrição embaixo da lista. Dá pra ✏️ editar enquanto está "solicitada" e 📄 ver/imprimir um PDF da solicitação (cabeçalho JP, tabela das peças, fotos, assinaturas). Solicitações antigas continuam aparecendo normal.
🧻 NOVO: Receber bobinas no app Qualidade — importe o XML da NF de papel e confira rolo a rolo pelo romaneio (nº, largura e peso reais), escolhendo o dono de cada bobina (JP ou terceiro — o sistema sugere pela operação da nota). Cada rolo vira uma bobina com código próprio (JP-BOB-0001…) e etiqueta com QR pra imprimir. No fim, confere se o peso bate com a nota.
🐛 CORREÇÃO IMPORTANTE na importação: pedidos com entregas parceladas (mesmo produto em datas diferentes — ex.: 8 entregas do 44959) estavam sumindo! O dedup ignorava a data e tratava como duplicata (106 itens viravam 68). Agora a data entra na chave e nada se perde. Também corrigido: datas que o Excel guardava como "data de verdade" viravam número.
🔒 Custos — acesso por pessoa: alimentar (lançamentos, clichê/faca) é admin + PCP; ver os resultados (custo total, lucro, salários) é só você + quem você liberar (no Painel de Custos, "Quem pode ver os custos").
📒 NOVO: Módulo CUSTOS (Centro de Custo) — só admin/financeiro. Painel de custo total + % por categoria; Ponto de Equilíbrio (quantas toneladas pra empatar + lucro + simulador); Lançamentos de insumos; Fixos & Funcionários (salário com encargos); Clichê & Faca por cliente; Evolução mês a mês.
🧾 Condições de pagamento: cadastro separado (7/14/21…) + campo no cliente.
⏱️ Urgente com prazo: chamado urgente tem 30 min pra iniciar. Passou disso, a manutenção recebe um aviso a cada 1 minuto até alguém iniciar (com contagem no card).
✅ Finalização em 2 fatores: a manutenção resolve, mas o chamado só fecha quando quem abriu dá o OK na solução — ou o PCP confirma aqui no central. Se não resolveu, reabre.
🏪 Compras: cadastro de Fornecedores + envio do pedido — cadastre fornecedores (WhatsApp + e-mail) e, ao gerar a OC, mande o pedido de compra direto pelo 📱 WhatsApp ou 📧 e-mail (mensagem já pronta). O card mostra o status "enviado via WhatsApp/e-mail".
📦 Manutenção acompanha a peça: dentro do chamado, a tag da peça agora é viva — "🛒 comprada · chega DD/MM" e, quando chega, "📦 PEÇA CHEGOU" com aviso sonoro.
🔧 NOVO: App de Manutenção (painel_manutencao.html) — fila de chamados por setor (⚡ Elétrica / 🔩 Mecânica), urgente fura a fila, preventiva sem prioridade, chamado de "ambos" visível pros 2, fotos, atender/resolver com solução registrada. O botão Manutenção do operador agora roteia por setor e tudo fica na ata aqui no central.
🛒 NOVO: App de Compras (painel_compras.html) — recebe as solicitações de peça da manutenção (com foto), gera Ordem de Compra numerada (OC-0001…), pipeline solicitada → comprada → recebida. Ata aqui no central.
🔬 Laudo turbinado: TODAS as caixas programadas entram sozinhas na fila; produção finalizada libera o valor total; laudo só finaliza com 3 fotos dos testes DIRETO da câmera ao vivo (galeria bloqueada, carimbo de data/hora) — e as fotos saem no PDF. Aviso sonoro de pedido novo.
🚚 Expedição enxerga o motorista: faixa "Entregas ao vivo" com o cheguei/entreguei (antes esse retorno se perdia).
👥 Cadastros novos: Manutentores (com setor) e Compradores.
🎯 Fim da divergência entre aparelhos: o banco agora é a ÚNICA fonte da verdade. Na carga, o servidor sempre vence — aparelho com cache velho não re-envia mais pedidos antigos (era isso que fazia um mostrar 82 e outro 164).
📥 Importação substitui, nunca soma: importar um relatório deixa o banco exatamente igual à lista importada (apaga os antigos). Acabou o acúmulo de importações (96+68=164).
🛟 Backup automático novo: 1x por dia, depois das 17:00 (mínimo 14h entre backups). O botão manual continua sempre disponível.
💣 v2.28.9 — removido o "relatório fantasma" 22/05: existia um relatório antigo (96 itens) embutido no código que se AUTO-CARREGAVA quando um aparelho abria com a lista vazia — e era salvo no servidor. Era a origem dos pedidos que "voltavam do nada" depois de cada limpeza. Removido o botão, os dados e a semente do boot. Vazio agora é vazio.
🎨 Visual novo — menu lateral: os módulos (Produção, Comercial, Cadastros, Expedição, Análises) viraram uma barra lateral à esquerda. Ao abrir Cadastros, os 13 itens aparecem agrupados (Clientes · Equipe · Produtos · Sistema) — acabou o monte de abas que cortava.
📱 Celular: a barra vira um menu ☰ que abre por cima — nada espremido, nada cortado, em qualquer tela.
⚡ Auto-atualização ativa (v2.28.6): o app se conserta sozinho ao detectar versão nova — operadores não mexem mais em cache.
📅 Cronograma de produção no painel do operador: o operador agora tem o botão Cronograma (no lugar do "Enviar registros", que já enviava sozinho). Mostra os horários de início e fim de cada caixa por turno, com almoço — calculado pelo PCP e espelhado pra ele. Só visualização: a liberação por chapa continua igual.
💰 IPI agora é padrão pra TODOS (15%): todo pedido já vem com IPI. Só fica isento quem tem carta de isenção válida. Resolve clientes (ex.: FK Grupo) que não pegavam o IPI.
📊 Relatório com 2 colunas: Total real (sem IPI) e Total c/ IPI, lado a lado. O CSV também.
🆔 Fim dos duplicados: cada pedido tem ID fixo por conteúdo. Reimportar ou importar em 2 aparelhos junta em vez de duplicar.
⚡ Cache do JS resolvido: arquivos versionados + service worker sem cache.
💰 IPI por cliente: campo "IPI (%)" no cadastro (novo já vem 15%). Soma no valor total do relatório — o preço unitário do produto não muda.
📄 Carta de isenção de IPI: anexa foto/PDF; cliente fica isento. Tem vencimento (vale 1 ano) com aviso 30 dias antes — carta vencida volta a cobrar IPI.
🗑️ "Apagar tudo" consertado: agora apaga de verdade no servidor e propaga pra todos os aparelhos (antes voltava ao atualizar). E só o admin original pode apagar dados — outros admins não.
🔗 Importação: corrigido o código que "comia" specs do produto (ex.: "33 VIGOR FATIADOS 12X150G" agora casa com a caixa cadastrada).
🔄 Sincronização do PCP consertada: mudanças do dia a dia (trocar status, editar pedido) voltaram a ir pro servidor e a chegar na hora no app do operador — antes ficavam presas só no navegador (resto da migração do Firebase).
📷 Fotos de ocorrências/manutenções voltaram a abrir: a foto subia mas o link apontava pro lugar errado no servidor; agora o link sai certo (local e produção).
🧹 App do operador: removida a etapa "Chapa chegou na máquina" (começa direto no ajuste) e botão Manutenção em largura total.
🧽 "Começar do zero" agora zera de verdade: o "Apagar TODOS os movimentos" e o "Limpar servidor" passaram a apagar também a carteira do PCP e os concluídos do operador (antes sobrava um pedido teimoso). E o app do operador limpa sozinho os concluídos/progresso que ficavam no celular assim que o sistema é zerado — não precisa mexer em cada aparelho.
🏭 Coluna "Processo" do PCP redesenhada (trilho de etapas): no lugar das barrinhas confusas, agora aparece o caminho do pedido pelas máquinas (ex.: ✂️ Slotter ▸ 📦 Coladeira) com cor por estado — verde = concluído, azul piscando = rodando agora, vermelho = parado, cinza = esperando — mais 1 barra geral e a quantidade. E ao passar o mouse em cima do pedido, abre um balão moderno mostrando qual máquina está rodando, o operador, há quanto tempo e o estado de cada etapa.
📲 Fim do "app preso em versão antiga": agora todos os apps usam um service worker no modo network-first — quando tem internet, ele sempre baixa o código mais novo sozinho (nunca serve versão velha do cache), e quando está offline usa a última versão salva. Resolve de vez o cache teimoso do PWA no iPhone. Obs.: cada aparelho precisa atualizar uma última vez (banner "nova versão" ou botão "🧹 Atualizar app") pra ligar o service worker; depois disso é automático.
🔧 Corrige a Coladeira presa em "esperando finalizar" mesmo com o Slotter já concluído. A causa: ao republicar os pedidos pro chão de fábrica, o PCP reescrevia a lista e apagava o que o operador tinha gravado (a liberação parcial e o "concluído" do corte). Agora o PCP preserva esses campos ao republicar, e a Coladeira passou a confirmar o "concluído" também pelo quadro compartilhado (à prova de sobrescrita).
🛟 Backup automático agora a cada 5 horas (era a cada 30 min) — pra não encher o PC de cópias. O cofre na nuvem continua guardando as últimas 48 (agora ~10 dias de histórico).
✅ Conclusão de pedido em tempo real entre operadores: quando um operador conclui um pedido, ele some da lista de todo mundo na mesma hora (antes só sumia no celular de quem concluiu, e dava pra outro produzir de novo). Usa um quadro compartilhado na nuvem gravado por merge (mesmo padrão da trava de pedido) — sem corrida de dados e funciona offline. A aba "Concluídos" mostra também os concluídos por colegas da mesma máquina (marcados "só leitura").
⏱️ Cronômetro durante a produção + passagem de turno (handoff) no app do operador: o tempo de produção aparece rodando também na tela de finalizar, com "faltam X caixas". Ao largar/encerrar o turno, o pedido fica disponível pra outro continuar — guardando quanto já foi feito, quem largou e a hora — e o cronômetro congela e retoma num segmento novo sem perder o tempo acumulado.
🛟 Backup automático COMPLETO a cada 30 min: agora salva uma cópia de tudo (caixas, clientes, vendedores, pedidos, chapas, papéis, cores…) num cofre na nuvem (últimas 48) e baixa uma no PC. Antes o backup só guardava pedidos+config (por isso os cadastros se perderam). Dá pra ver e restaurar os backups da nuvem no botão "☁️ Cofre" do backup. Só faz backup se os dados estiverem saudáveis (não grava cópia vazia).
🛟 Proteção contra perda de dados (caixas, clientes, vendedores): (1) nunca salva lista vazia nem encolhida sem confirmar (disjuntor); (2) só lê/grava depois do login; (3) erro de leitura não é mais engolido — bloqueia o salvar até recarregar; (4) desligado o salvamento automático que recriava clientes em branco. Corrige o incidente de esvaziamento dos cadastros.
🧭 Menu não abre mais "misturado": ao abrir o sistema, o menu já mostra só as abas do módulo ativo (Produção) — antes apareciam abas de todos os módulos juntas até você clicar. Corrigido (o filtro do módulo passou a ser a última etapa, depois das permissões).
🔒 Blindagem pra fechar as regras (bastidor): garanti que toda leitura do app do operador (inclusive a lista de login) só acontece depois do login anônimo. É o preparo final pra fechar o banco sem travar nada. Não muda nada visível.
🔄 Aviso de versão nova (fim do cache velho no celular): os apps agora avisam quando há atualização — aparece a barra "🔄 Nova versão disponível — toque para atualizar", e num toque o app pega a versão nova (sem precisar apagar/reinstalar). Funciona até no cache teimoso do iPhone. Se estiver sem internet, não atrapalha nada — só avisa quando dá. Vale em operador, expedição, laudo, motorista, vendedor e no sistema.
🔐 Login anônimo do Firebase nos apps de chão (preparação de segurança): operador, expedição, laudo, motorista e vendedor agora fazem um login invisível no Firebase ao abrir, antes de ler/gravar. É a base pra fechar as regras do banco depois sem travar os apps. Não muda nada pro usuário (o login de nome/PIN continua igual) e tem proteção anti-travamento se a internet falhar. As regras do Firestore continuam abertas — serão fechadas num próximo passo.
📐 Medida da chapa: largura primeiro na visualização: nas listas/previews a chapa mostra largura × comprimento (coluna "Medida chapa" do PCP, lista de caixas, preview e itens do orçamento). No cadastro da caixa o comprimento continua primeiro (padrão universal C × L × A).
📏 Medida da chapa na lista do PCP: nova coluna entre "Produto/Cód." e "Status" mostrando o tamanho da chapa (comprimento × largura em mm) de cada pedido, puxado do cadastro da caixa. Bate o olho e já vê a medida sem abrir nada.
📲 Enviar pro operador sem baixar arquivo: o botão "P/ Operador" agora só publica no Firebase (tempo real) — parou de baixar aquele .json de backup que não era usado.
🖼️ Logo do cliente na etiqueta do palete: no cadastro do cliente tem um campo pra subir a logo (entre Identificação e Contatos). A logo vai pro Storage e aparece na etiqueta do palete ao imprimir — tanto no PCP quanto no app do operador (viaja junto do pedido).
🏷️ Etiqueta do operador igual à do sistema: a etiqueta impressa pelo operador agora é idêntica à do PCP — com QR Code de expedição e sem aquele campo de "Conferido por / Assinatura" que não era usado.
🔒 Trava de pedido no app do operador: quando um operador abre um pedido, ele fica "🔒 em uso por Fulano" pros outros — dois não pegam o mesmo ao mesmo tempo. Sincroniza na hora (tempo real). Ao finalizar, a trava sai sozinha. No fim de turno, se ficou em andamento, volta a ficar disponível pra outro continuar de onde parou (preserva o parcial). Trava de aparelho que sumiu/offline expira sozinha (12h). Corrigido também o bug que fazia um celular apagar o progresso do outro.
🔄 App do operador 100% em tempo real: trava, caixas cadastradas e ordem de produção do PCP agora atualizam sozinhos no app do operador (corrigido um trecho que ligava os listeners antes do Firebase iniciar — por isso só vinha do cache / botão "recarregar").
📤 Registro de produção sobe sozinho: ao finalizar um pedido, o registro vai pro sistema na hora (sem precisar clicar em "Enviar"). Se estiver offline, fica guardado e sobe sozinho quando a internet volta.
📅 Fluxo de Produção — alerta de atraso + produção real: o cronograma agora marca em ⚠ vermelho (atrasado) os pedidos que terminam depois da data de entrega e em 🟡 âmbar (apertado) os que terminam no mesmo dia — vale no Gantt e no Calendário, com a data de entrega na lista. E o cálculo agora desconta o que os operadores já produziram (caixas registradas no chão), então a fila e as datas refletem a situação real, não o pedido inteiro do zero.
🔒 Apps de chão em fluxo fechado: tirei o botão 🏠 "Trocar de painel" dos apps de operador, expedição e laudo. Agora o único jeito de sair é o "Sair", que volta pro login do próprio app (nome + PIN/senha). Eles nunca mais caem no menu geral com os outros painéis.
🔒 Menu (index) protegido sem PIN: a grade de painéis só abre em aparelhos que já entraram no PCP/sistema (login). Operador vê "menu restrito" e usa o link direto do app dele. Quem está no PCP transita livre. (Some o acesso ao sair do sistema.)
🛠️ Painel ADM (Cadastros → ADM, só admin): atalho pra abrir/testar cada app numa nova aba + QR + link, num lugar só.
🔮 Simulador: caixas filtradas por cliente — ao escolher o cliente, só aparecem as caixas dele (não mais todas embaralhadas).
🧭 Link do mapa na escala encurtado (tinyurl) — a mensagem do WhatsApp não fica mais com aquele link gigante (cai no link completo se o encurtador falhar).
🔮 Simulador de prazo turbinado (Fluxo): monta um pedido completo (cliente + vários itens caixa+qtd), calcula a entrega final, a data limite da chapa (Onduladeira) e o plano de entregas parciais, encaixando na fila real. Botão Gerar proposta (PDF). Recalcula sozinho ao mudar turno/capacidade.
🩹 App do operador — corrigido "NaN dias": data de entrega inválida não quebra mais o cálculo (mostra "—").
🪶 App do operador — menos memória (celular simples): não guarda mais o histórico de alterações das caixas nem imagens base64 no cache, e removido carregamento duplicado — pra evitar o erro de "insuficiência de memória".
🏭 Fluxo de produção / Cronograma (Comercial → Fluxo/Cronograma): cadastro de capacidade das máquinas (Onduladeira/Slotter/Coladeira/Grampeadeira), cálculo de prazo encadeado (a fila passa em sequência respeitando os turnos), Gantt e calendário mensal com % de ocupação por dia (verde/amarelo/vermelho), e simulador de prazo ("se entrar agora, fica pronto em..."). Parte 1 (previsão). Só PCP/Comercial.
✂️ Slotter desconta as perdas automaticamente: ao finalizar, o sistema calcula a quantidade BOA (total − perda de ajuste − perda de produção) e passa só ela pra próxima etapa. A meta da coladeira/grampeadeira usa a quantidade boa (ex: 110 − 1 − 10 = 99), não o total. Nunca passa número negativo. O operador do Slotter vê a conta na tela.
🔗 Importação de relatório vincula a caixa ao pedido: pra cada item, casa o código (ex: "01-01") com o cadastro de caixas (match exato). Casou → vincula e atualiza o preço da caixa (o relatório sempre vence, com histórico). Não casou → entra na lista "não encontradas" no resumo, pra resolver na mão.
🗓️ Última data de entrega na caixa: gravada do relatório (aparece no cadastro). Datas diferentes = lançamentos separados.
📊 Resumo da importação: quantas vincularam, lançamentos, preços/prazos atualizados e a lista das que não casaram.
📱 Layout responsivo pro celular: abas (módulos e sub-abas) com rolagem horizontal "arrasta pro lado", botões e ícones maiores pro dedo, e as tabelas de cadastro viram cartões empilhados (sem precisar rolar pro lado). No PC continua igual.
🖨 Ajuste no PDF da semana: o 1º dia agora sai junto do cabeçalho (acabou a página em branco no começo).
👤 Operador na ocorrência: o nome do operador agora aparece no card da ocorrência (estava salvando vazio).
📲 Link + QR por app (no menu): cada app tem um botão pra pegar o link direto e o QR Code pra mandar pra pessoa certa (sem passar pelo menu) e instalar no celular. Vendedor, Motorista e Escala agora também são instaláveis (adicionar à tela).
📥 Importação de ficha aceita .XLS além de PDF (Cadastros → Caixas), lendo o arquivo do sistema direto.
🖨 Exportar PDF do cronograma: botão "Este dia" e "Semana (7 dias)" — com a mesma cara da tela, abre numa janela rápida pra imprimir/salvar em PDF.
⚡ Turno extraordinário (Config): liga/desliga turnos estendidos (ex: 12h, 05→17 e 17→05) e o cronograma recalcula com mais horas/dia → menos atrasos. Almoço por horário fixo de cada turno.
🔗 Cadeia clara no cronograma: badge "Esperando coladeira/grampeadeira" com a qtd que já saiu da slotter, qtd do pedido ao lado do nome, e chapas em vermelho quando vierem abaixo do pedido.
📄 Importação de ficha por PDF (Cadastros → Caixas): lê os dados de entrada do PDF (cliente, código, medidas, composição, onda, cores, fechamento, paletização) e o sistema recalcula gramatura/riscador/peso. Cadastra papéis/cores/chapa que faltam e a caixa — tudo com revisão e comparação calc×PDF. Aceita 1 ou vários.
📦 Rótulo "Maleta aba transpassada inferior" no tipo de caixa.
📦 Novo tipo de caixa "Aba transpassada inferior" no cadastro — a última aba do riscador = largura inteira (L), o resto idêntico à maleta normal. Maleta normal inalterada.
🗑️ Limpar Dados (Cadastros, só admin/PCP) — zera os dados de movimento (pedidos, produção, estoque, cargas, escalas, entregas, ocorrências, manutenções, laudos, orçamentos, chat) pra começar do zero
🔒 Confirmação dupla (digitar APAGAR / APAGAR TUDO) · apaga nuvem + aparelho · cadastros nunca são apagados
📶 Modo offline (parte 1) — os dados ficam salvos no aparelho; se a internet cair, dá pra ver e lançar normal e sincroniza sozinho quando voltar
🟢🟡 Tarja de status de conexão no topo de todos os painéis (Online / Sem internet)
🆕 Novo status "Pronto" — quando a produção termina, o pedido fica Pronto (aguardando etiqueta)
🖨️ No PCP, botão de imprimir etiqueta no pedido Pronto → vira Pronto p/ Carregar e entra no Estoque PA
🔒 Coladeira/Grampeadeira não finaliza antes do Slotter/Corte concluir
✅ App operador: pedido fica em Concluído por 24h (some sozinho depois)
🏁 App operador: botão Finalizar turno com total de caixas × peso + tempo e qtd de ajustes
📊 Barras de progresso de produção no PCP e no app do operador
✂️ Barra da Chapa (Slotter): total de chapa × quanto já foi cortado
📦 Barra da Caixa (Coladeira/Grampeadeira): quanto já foi produzido
📤 Liberação parcial do Slotter — corta parcial e libera pra Coladeira/Grampeadeira começar JUNTO, sem esperar finalizar tudo
🎨 Cores por andamento (amarelo → azul → verde), número + % sempre visíveis e atualizando ao vivo
🤝 Novo App do Vendedor — login por nome + PIN de 4 dígitos (igual ao motorista)
👀 O vendedor vê só os clientes vinculados a ele, com busca por nome
📊 Cada pedido aparece com a fase: 🟡 Esperando programação · 🟠 Programado · 🔵 Produzindo · 🟣 Pronto aguardando carga · 🟢 Em rota · ✅ Entregue
📨 Botão Solicitar orçamento — o vendedor manda o pedido e o PCP analisa depois (nova aba 📨 Solicitações no Comercial)
🔑 Cadastro de vendedor agora tem campo de PIN de acesso ao app
📦 Número do pedido viaja por toda a cadeia — agora aparece também no Laudo (lista, detalhe, PDF e mensagens de WhatsApp/e-mail)
🔗 Vínculo cliente↔caixa mais robusto: ao lançar pedido, "Frisokar", "FRISOKAR LTDA" e "Frisokar Ltda." passam a casar igual (ignora acento, maiúscula, pontuação e sufixos jurídicos)
⚡ Se o cliente tem só uma caixa cadastrada, o sistema já seleciona ela sozinho no pedido
✍️ Carregamento manual na expedição permite digitar o nº do pedido e marca com ✍
🚚 Número do pedido também na escala e no app do motorista (embaixo de cada destino)
📦 Sugestão automática de caixas por palete no cadastro da caixa
🧮 Conta: espessura da onda × 2 (a cola dobra a chapa) × peças por amarrado = altura do pacote → (altura máx − altura do palete) ÷ altura do pacote = camadas → lastro × camadas × amarrado
📝 Campo Lastro virou número único (pacotes na base) + novo campo Altura do palete (mm) editável (padrão 150)
📲 No app da Coladeira/Grampeadeira o popup de paletização já vem preenchido com a sugestão — o operador pode mudar se precisar
⚠️ Se faltar dado no cadastro, o popup avisa o que falta
🐛 Correção: perdas do operador agora aparecem na análise
✅ Perdas (setup e produção) são persistidas no Firebase ao finalizar o pedido
✅ Antes elas sumiam quando o pedido era concluído — agora ficam no histórico
🔧 Correção do botão "Voltar/Fechar" que ficava atravessado no painel do operador
📍 Endereço do cliente em campos separados (rua, número, bairro, cidade, UF, CEP) + ponto de referência
🧭 Botão "Abrir rota no GPS" na escala — motorista escolhe Waze ou Google Maps
🔗 Link de rota também vai junto na mensagem da escala postada no grupo
✅ Endereço puxa automático do cadastro do cliente pro destino da viagem
📋 Novo status "Material disponível"
✅ Digitou a qtd de chapa (saída da onduladeira) → status vira Material disponível automático
✅ Só muda se o pedido ainda não começou (Programado / Esperando / Reprogramado)
✅ Zerou a chapa → volta pra "Esperando programação"
🔄 Importação mais inteligente: compara por pedido + caixa + data exata
🛡️ Itens com material disponível ficam congelados no status e na qtd de chapa
✅ O resto (cliente, código, qtd, valor, obs) atualiza normal na reimportação
🚚 Novo status "Carregado" — automático quando a expedição finaliza a carga
🧮 Qtd produzida corrigida: conta só o processo final de fechamento (Coladeira → Grampeadeira → Corte e Vinco manual). Slotter não soma mais como caixa pronta
🔬 App Laudo turbinado: botão sempre liberado, dados do operador automáticos, cores e miniatura da arte no laudo
📱 "Postar no Grupo" agora abre o WhatsApp puro
✅ Copia a mensagem pra área de transferência
✅ Abre o WhatsApp (app no celular / Web no PC) na tela inicial
✅ Usuário escolhe o grupo na hora e cola a mensagem
🎯 Funciona nos 3 lugares: Expedição (carga finalizada), App de Escala (escala do dia), Sistema PCP (escala do dia)
📊 5 rankings de ocorrências (cliente, fornecedor, tipo, onda, chapa)
🔎 Detalhamento por cliente expandível
📋 9 tipos de ocorrência (Medidas, Descolamento, Abaulada, Úmida, Refile, Trinca, Empenamento, Mancha, Outro)
🎬 Botão "Carregar exemplos" pra preview dos rankings
⚠️ Sistema de Ocorrências de Chapa
📸 Operador tira foto direto pela câmera (até 6 fotos, comprimidas)
⏸️ Registra ocorrência pausa o pedido automaticamente
📊 Módulo Análises → Ocorrências com filtros, rankings, fotos em galeria
📱 App dedicado de Escala (painel_escala.html) pra gerente PCP no celular
🔐 Login email/senha (admin/pcp) · CRUD de viagens · cadastros rápidos
📢 Expedidor posta no grupo ao finalizar carga (botão na tela de sucesso)
🔗 Escala integrada à Expedição (vários destinos por viagem, status automático)
📊 Status: ⏳ aguardando → 🟡 parcial → ✅ carregado → 🚚 saiu
🚛 Módulo de Escalas de Caminhões + Cadastro de Caminhões
📅 Viagens agrupadas por caminhão · 🕗 horários · ↩️ retorno
📱 "Postar no grupo" + "Avisar motorista"
✏️ Editar item do orçamento direto na lista
🎨 Destaque visual em roxo durante edição
👁️ Visualizar orçamento antes de enviar (preview JP)
📱 Enviar por WhatsApp · 📧 E-mail · 🖨️ Imprimir / PDF
⚖ Alerta de peso mínimo agora é por item (não soma)
⚖ Cadastro de chapa: campo "Peso mínimo de produção (kg)"
📊 Orçamento: bloco "Peso por item" com alerta visual de mínimo
📐 Cadastro de Chapas (3 ou 5 camadas de papéis · gramatura calculada)
🔄 Orçamento agora usa chapa em vez de papel solto
🐛 Bug fix: número do orçamento sempre auto + preços em formato BR
💰 Novo módulo Comercial · Orçamentos
📐 Calcula chapa por estilo (Maleta B/C/BB/BC + Corte e Vinco)
🌊 Compensações de onda editáveis
🧾 ICMS/IPI editável + opção "sem IPI"
✅ Orçamento aprovado → vira caixa cadastrada + pedido vinculado
📦 Ficha por tipo de operador: Coladeira/Grampeadeira veem PALETIZAÇÃO, Slotter/Corte e Vinco veem ARTE
🖼️ Imagem da paletização no cadastro de caixa
📐 Campo Lastro (L × C) com cálculo automático
⚡ PDF mais robusto: espera carregar + botão "abrir em nova aba"
🔬 PDF da arte em alta resolução (renderiza 3x maior pra ficar nítido com zoom)
🔍 Código de barras e detalhes finos legíveis mesmo ampliando
📄 Novo visualizador de PDF da arte (Fit Page + pinch-zoom + multipágina)
📱 Funciona no iPhone, Android e desktop
🏠 Página inicial com menu central — todo mundo acessa o mesmo link
🎨 4 cards coloridos para escolher o painel
🧠 Menu inteligente: lembra qual painel a pessoa escolheu
🔄 Botão "🏠 Trocar painel" no header de cada PWA
🔄 Botão "Recarregar dados" no app operador (header + aviso de caixa não cadastrada)
📊 Contador de caixas carregadas visível pro operador
🔍 Match muito mais flexível: ignora hífens, underscores, pontos
🔎 Logs detalhados no console pra debug
🐛 Fix da ficha técnica no operador: agora aparece sempre, incluindo medidas, composição, arte e PDF
🔗 Match por caixaId (vínculo direto): pedidos cadastrados na v1.6.4+ encontram a caixa exata
🔍 Match fuzzy: ignora espaços, zeros à esquerda e maiúsculas/minúsculas
🎯 Match parcial: código "19" encontra caixa "19 KETCHUP 900ML"
⚠️ Aviso amigável quando caixa não tá cadastrada
🔐 Auto-registro de usuários: quando alguém loga pela primeira vez, é registrado automaticamente como "aguardando perfil"
👥 Modal de usuários melhorado: mostra TODOS os usuários, inclusive os sem perfil (destaque laranja)
🔔 Badge no botão Usuários: mostra quantos usuários estão aguardando você definir o perfil
📊 Tracking de login: total de logins + último acesso de cada usuário
🛡️ Auditoria: registra quem definiu o perfil e quando
⚡ Fases em tempo real no cronograma: PCP vê o que cada máquina tá fazendo
🎨 Badges: 🔵 Programado · 🟡 Em ajuste · 🟢 Em produção · 🔴 Parado · ⚪ Finalizado
🛑 Motivo de parada visível + tempo parado
📊 Progresso em produção (%) + 👤 operador responsável
⏱️ Tempo decorrido em cada fase ("há 23min")
🐛 Fix do cálculo do riscador para maleta normal:
• Maleta normal / FECO: ABA × A+alt × ABA × 0 × 0 (2 abas iguais a (L+L1)/2)
• Bandeja / Auto-piso: ABA × A+alt × L+compL1 × 0 × 0 (só aba de cima)
• Modelo agora afeta a fórmula automaticamente — recalcula ao trocar o modelo
🔧 Fix aplicado também na ficha técnica do painel do operador
👥 Cadastro de Clientes completo: nome, CNPJ, e-mail, WhatsApp, endereço, contato, observações
🔄 Migração automática: clientes que existiam em pedidos/caixas agora têm cadastro (incompleto, mas presente)
📊 KPIs de clientes: total, completos, incompletos, vínculos (caixas + pedidos)
⚡ Validação inteligente: hint no cadastro de pedido/caixa avisa se cliente está incompleto
🚀 Cadastro rápido: botão "cadastrar agora" no pedido abre modal de cliente, salva e volta selecionado
🐛 Fix do app de laudo: agora mostra todos os pedidos programados (bug do filtro statusOp)
🔐 Auto-logout 12h nos 3 PWAs (operador, expedição, laudo) — link copiado fica seguro
🔗 Cadastro de pedido vinculado: cliente e caixa agora vêm do cadastro (não é mais texto livre)
🔄 Migração automática: pedidos antigos vinculam sozinhos com caixas pelo match cliente+código
➕ Botão "+ Cadastrar caixa agora" no pedido: abre modal de caixa, salva, e volta com a caixa selecionada
🚚 Nova aba "Por motorista" no histórico do expedição — mostra paletes detalhados por cliente
🔄 Sincronização de cronograma: ordem do PCP reflete no painel do operador em tempo real
📊 Registro de perdas de chapa no ajuste e na produção (operador registra, PCP vê tudo)
📈 Nova aba "📊 Perdas" com KPIs, top 5 motivos, filtros e export CSV
🛑 13 motivos de parada (era 6) — agora com clichê, papel, tinta, refeição, manutenção, PCP, turno
🚛 Card "Motoristas em rota" no app de expedição com botão "Voltou" pra liberar motorista (fix do Gildo!)
⚡ Progressos do operador (setup/produção/parado) sincronizam em tempo real com o sistema PC
✨ Ficha de palete A4: cabe agora em 1 folha (era estourando)
✨ Referência com auto-ajuste de fonte (códigos curtos = fonte gigante, longos = compacta)
✨ Qtd no Palete com auto-ajuste de fonte (até 9.999 caixas, fonte cresce conforme menor o número)
🗑️ Removido: linhas de "Conferido por" e "Carimbo / Assinatura" (não usadas)
🆕 Painel de Laudo PWA (4ª PWA mobile) — controle de qualidade técnico
✨ Etapa 1: testes durante a produção (qtd chapa + gramatura + coluna) — até 3 testes
✨ Etapa 2: finalização com NF + Mullen + espessura + lote + umidade + observações
✨ Geração de PDF A4 padrão JP com tabela ✓ OK / ✗ NOK (tolerância ±5%)
✨ Envio direto: WhatsApp, e-mail, imprimir
✨ Cadastro de laudistas com login por código (igual operador/expedição)
✨ Velocidade da Grampeadeira adicionada (Slotter + Corte&Vinco + Coladeira + Grampeadeira)
✨ Sugestão automática de velocidade nas 4 máquinas
✨ Valor unitário automático da caixa (R$/kg × peso)
✨ Upload de arte/layout da caixa (PDF + imagem)
✨ App do operador mostra arte, clichê, faca, cores antes de iniciar
✨ Auto-busca no cadastro ao importar pedido do XLSX
✨ Tela técnica completa pro operador (medidas riscador + impressora)
✨ Cadastro de papéis (K12, M11, T15...) com sincronização Firebase
✨ Cadastro de caixa expandido com 11 seções: composição de chapa, compensações por aba, cores, etc.
✨ Cálculos automáticos: medidas impressor + riscador + área + peso unitário
✨ Sugestão de velocidade baseada no histórico real de produção
✨ Histórico de alterações da caixa (auditoria completa)
✨ Detecção de produção parcial (tolerância 5%) com banner pulsante no dashboard
✨ Modal de decisão do PCP: Aceitar Parcial ou Reprogramar Diferença
✨ Caixas vão pro estoque mesmo reprogramando
✨ Auditoria das decisões (quem decidiu, quando, qtd)
✨ Fluxo de 3 quantidades: pedido, chapa pronta, produzido
✨ Operador finaliza por etapas (Slotter → Coladeira/Grampeadeira)
✨ Auto-publicação no Estoque PA ao concluir todas etapas
✨ Sincronização tempo real das etapas (Firebase)
✨ Importação inteligente: preserva pedidos em produção
✨ Cronograma mostra pedidos "FINALIZANDO" (badge verde tracejado)
✨ Roteiro "sem acabamento" agora passa por Coladeira ou Grampeadeira
✨ Etiqueta A4: peso do palete, hora, carimbo, QR code 50mm
🎉 Sistema inicial JP Embalagens
📋 Dashboard, Relatório, Estoque, Cadastros, Expedição, Análises
📲 3 apps: Sistema (PC) + Operador (PWA) + Expedição (PWA)
☁️ Sincronização Firebase em tempo real
🎨 Identidade visual JP (logo + paleta azul)
💡 Sobre o versionamento: Os arquivos têm a versão no nome (ex: sistema_v1.9.6.html). Se algo der errado, é só voltar pra versão anterior.