FJFrigo · Relatórios · menu 3-8 Indicadores — 385, 38D e 38E

Painel do Almoxarifado, Acuracidade e Transferências

O estoque do almoxarifado (valor, cobertura, ruptura, excesso, parado, ABC e consumo), a acuracidade do inventário (sobras e faltas) e as transferências entre filiais (trânsito, entradas não localizadas, compra evitável): de onde vem cada número e como conferir.

Telas: Painel do Almoxarifado (385), Acuracidade do Inventário (38D), Transferências entre Filiais (38E)Origem: desenho novo, sem legadoSaída: painel em tela e XLS (sem PDF)Grava: nada

Bloqueia

Recusa e não gera. HTTP 200 com statuscode 400 e a frase indicada.

Aviso

Comportamento que surpreende sem ser erro — origem da maioria dos chamados de "o número não bate". Parte sai como painel de avisos na tela.

Mesma base de estoque

38D e 38E usam a apuração do 385 (view do inventário 3332, custo da filial, moeda). Sem a view, os três saem zerados.

Cache de 10 min

A apuração fica em memória por usuário e filtros; só o Atualizar do 385 a refaz na hora.

A

Visão geral e base comum

385, 38D e 38E leem o mesmo estoque

Os três são desenho novo, sem legado, do grupo 3-8 Indicadores, e dividem a mesma base: o estoque do almoxarifado apurado pelo 385 (RelatorioPainelAlmoxarifadoService.apuracao). O 38D e o 38E chamam essa apuração por dentro; quem quebra o 385 quebra os três.

OpçãoPergunta que respondeJanela de tempo
385 Painel do AlmoxarifadoQuanto há em estoque (12 meses), quanto cobre, o que falta, o que sobra, o que está parado; ABC × cobertura; consumo por setor ou centro de custo.Data-base (saldo, custo) + janela de consumo de 30/90/180 dias que termina nela.
38D Acuracidade do InventárioQuanto o inventário ajustou (sobras e faltas) e se o erro volta (itens ajustados em 2+ meses).Período livre (padrão 1 ano); o estoque é o da data final.
38E Transferências entre FiliaisO que foi transferido, se o destino lançou a entrada, quanto tempo de trânsito e que compra poderia ter sido evitada.Período livre (padrão 90 dias); a entrada é procurada até hoje.

O que é "estoque" aqui

Saldo = soma de almoxarifado_movimentacao_analitica.quantidade (a view do inventário 3332, por tenant) até a data-base, por filial × produto × mês; o saldo de cada fim de mês é a soma acumulada. A view conta a saída 1178, tira a 11115 e a saída de cabeçalho excluído — por isso não é a regra do SaldoAlmoxarifado (a da CAN).

Custo = o último custo de entrada da filial (compra de tipo diferente de 1158, ou lançamento manual de entrada), em moeda local (valor_total_ml; manual: valor_ml, ou valor quando a moeda é a local). O custo da empresa só vale quando a filial nunca teve entrada com valor até aquele mês. Item sem custo entra com valor zero e aviso.

Imobilizado fica fora (almoxarifado_produto.imobilizado = 'T'); os filtros Grupo e Excluir grupo (almoxarifado_grupo) valem para tudo. Saldo negativo fica fora do valor em estoque, com aviso.

Cache. A apuração do estoque fica em memória 10 min por usuário + filtros + data-base + janela + moeda. Só o botão Atualizar do 385 refaz na hora; o 38D e o 38E não têm Atualizar e reaproveitam essa apuração.

Moeda. Padrão = moeda local; fora do Brasil (parametros.codicfj ≠ 004) a janela do 385 abre em dólar (112), o mesmo do IFRS, e o painel tem o seletor U$ | Moeda local. Estoque converte pela cotação de cada fim de mês; consumo, pela do dia (mv.data = DATE(data_emissao)).

B

385 — Painel do Almoxarifado

Filtros, tela, números e classificação

Janela de filtros → Ver em tela (painel) ou XLS (todos os itens; não há PDF).

Filtros e opções

CampoPadrãoEfeito
Data-baseHojeData de corte do saldo e do custo; a janela de consumo termina nela. Data futura vira hoje. O campo "de" não existe.
Filial (multi)Todas as do usuárioO saldo é sempre lido de todas as filiais do usuário (para o "saldo nas outras filiais"); a lista só traz as pedidas.
Grupo / Excluir grupo (multi)Todos / nenhumO grupo IMOBILIZADO de central tem equipamento sem a marca imobilizado = 'T' (embaladora de R$ 400 mil de Iporã aparecia como "parado"): use Excluir grupo.
Janela de consumo90 dias30, 90 ou 180. Outro valor vira 90.
Consumo porSetorSetor = almoxarifado_saida.idalmoxarifado_setor; Centro de custo = almoxarifado_produto.idcentro_custo_venda (como o 3324).
Moeda conversãoMoeda local (dólar fora do Brasil)Ver seção A.

O que o painel mostra

BlocoConteúdo
IndicadoresValor em estoque (× fim do mês anterior; itens com saldo); Cobertura média (valor em estoque × janela ÷ consumo em valor, em dias); Ruptura (itens); Excesso (itens e valor excedente); Estoque parado (itens e valor); Consumo (× janela anterior).
EstoqueValor no fim de cada mês (12 meses, as 6 filiais de maior valor; clicar num mês — em qualquer ponto — mostra todas as filiais daquele mês); valor por tempo sem saída (Até 90, 91 a 180, 181 a 365, Mais de 365 dias, Nunca saiu; o clique abre a lista).
Curva ABCOs 40 itens de maior consumo (cor = classe) e a matriz Classe × cobertura (3 × 3; a célula abre a lista). A = até 80% do consumo acumulado, B = até 95%, C = o resto; cobertura baixa < PAINEL_ALMOX_COBERTURA_MIN dias, alta > _MAX. Seletor de filial recalcula a classe só com os itens da filial.
ConsumoPor setor (ou centro): janela × mesmo período do ano anterior (os 15 maiores; o clique abre o mês a mês por grupo), com desvio = consumo diário da janela ÷ o dos 180 dias antes (destaque acima de ±25%). Também segue o seletor de filial.
ListasRuptura, excesso e parados (500 linhas na tela; o XLS traz todas): produto, grupo, saldo, mín., máx., consumo/dia, cobertura, última saída.
XLSAba de itens (filial, código, produto, un., grupo, situação, ABC, saldo, mínimo, máximo, consumo da janela, consumo/dia, cobertura, última saída/entrada, "sem saída há", custo unit., valor em estoque, excedente, saldo outras filiais), Resumo por filial e Consumo por setor/centro.

Classificação de cada item (filial × produto)

SituaçãoRegra
NEGATIVOSaldo < 0 na data-base. Fora do valor em estoque; aviso N item(ns) com saldo negativo na data-base (fora do valor em estoque; ver o XLS).
RUPTURASó item consumido na janela naquela filial. Com mínimo no cadastro: saldo ≤ mínimo. Sem mínimo: cobertura < PAINEL_ALMOX_COBERTURA_MIN (15). Cobertura = saldo ÷ consumo/dia, em dias inteiros para baixo.
EXCESSOItem consumido, fora da ruptura, com saldo > máximo (cadastro) ou > consumo/dia × PAINEL_ALMOX_COBERTURA_MAX (180). Excedente em valor = (saldo − teto) × custo.
PARADOSem consumo na janela, saldo > 0 e nenhuma saída (de qualquer tipo) há mais de 180 dias.
NORMALO resto.

O par mínimo 1 / máximo 2 é ignorado (decisão do usuário, 03/10): 18.271 dos 20.609 produtos com máximo em central têm esse par, que é enchimento de cadastro. Ele vale como "sem mínimo/máximo" e o item cai na cobertura em dias. Efeito medido: excesso 768 → 701 itens (excedente R$ 3,0 → 2,0 mi); o milho de Entre Rios (3 dias de cobertura) passa a ruptura. O par também some da grade.

Consumo = saída dos tipos de PAINEL_ALMOX_TIPOS_CONSUMO (117); remessa e transferência não contam. Valor = custo_total × câmbio da linha quando a moeda da linha não é a local (Paraguai tem saída em U$/EUR/R$).

C

38D — Acuracidade do Inventário do Almoxarifado

O que o banco permite medir

Não existe contagem gravada — nem no legado (menu242/menu243 só tratam 11187/11188 como tipos de compra/saída) nem no ceif. O inventário entra como ajuste lançado à mão: compra do tipo 11187 ("Ajuste Inventario Entrada Almox" = sobra) e saída do tipo 11188 ("Ajuste Inventario Saida Almox" = falta). Só a divergência fica registrada, nunca o item que bateu: a acuracidade clássica (% de itens contados sem divergência) não sai do banco.

IndicadorCálculo
Sobras, Faltas, Líquido, BrutoSobras = almoxarifado_compra_produto.valor_total_ml dos tipos de PAINEL_ALMOX_TIPOS_AJUSTE_SOBRA; faltas = custo_total × câmbio das saídas de _FALTA; líquido = sobras − faltas; bruto = sobras + faltas. Pela data da compra/saída, imobilizado fora.
Ajuste bruto % do estoqueBruto ÷ valor em estoque da data final (apuração do 385). É 12 meses de ajuste contra a foto de um dia: pode passar de 100% por filial.
Itens ajustados e % dos itens com saldoPares filial × produto com algum ajuste no período ÷ itens com saldo > 0 na data final. O numerador inclui itens que hoje têm saldo zero: o percentual pode passar de 100% (ver achados).
Ajustados em 2+ meses (recorrentes)Pares filial × produto ajustados em dois meses ou mais: "o erro volta" (cadastro, unidade ou baixa errada).
Saldo negativoItens com saldo < 0 na data final (do 385): saída sem entrada lançada.
Lançamentos manuaisalmoxarifado_lancamentos_manuais fora da taxa, num quadro à parte por operação e por justificativa (misturam "AJUSTE DE SALDO NEGATIVO", implantação de saldo, "VEICULOS PARA VENDA", "AJUSTE PARA NF DE VENDA/TRANSFERENCIA"; só 274 de 1.045 saídas manuais de 12 meses têm justificativa). Valor: valor_ml (ou valor em moeda local), com sinal pela operação E/S.

Telas: indicadores, sobras e faltas mês a mês, por grupo (os 12 de maior ajuste), por filial (estoque, sobras, faltas, líquido, bruto %, % dos itens, recorrentes, manual entrada/saída), itens ajustados, por usuário (quem lançou — idusuario_incluiu) e o quadro dos manuais. XLS: itens, por filial, por usuário e manuais (sem PDF). No Paraguai não há nenhum 11187/11188: o acerto lá parece ir por lançamento manual.

D

38E — Transferências entre Filiais do Almoxarifado

Saída → entrada e compra potencialmente evitável

Parte das saídas do tipo PAINEL_ALMOX_TIPOS_TRANSF_SAIDA (1151) no período, procura a entrada de _TRANSF_ENTRADA (1152) no destino e mede o trânsito. A ligação saída → entrada depende do build do tenant (o 242 do legado não liga nem confere nada):

CasoComo acha o destino e a entrada
almoxarifado_compra.idalmoxarifado_saida preenchido (Paraguai; o documento da entrada fica vazio)Vale essa ligação; o destino é a filial da entrada.
Campo vazio (central: vazio em todas as entradas)Destino = a filial cujo filial.cnpj (sem ., /, -, espaço) é o emitente.cnpj_cpf da saída — só se o CNPJ é de uma filial só (no Paraguai todas têm o mesmo RUC e tudo caía em Asunción). Entrada = a do tipo de entrada na filial de destino com o mesmo documento sem zeros à esquerda, de 5 dias antes a 180 dias depois da saída (a primeira). O emitente da entrada não é conferido (em Margarida, 61, as 981 entradas usam o emitente genérico 1005623).
Situação da saídaQuando
Com entrada localizadaAchou a entrada (ligação direta ou por CNPJ + documento).
SEM_ENTRADADestino identificado, entrada não achada: o destino não lançou, ou lançou com outro documento.
SEM_DESTINONenhuma filial com o CNPJ do emitente (ou CNPJ de mais de uma filial). Fora do percentual de localizadas.

Indicadores: valor transferido; % com entrada localizada (sobre as saídas com destino); trânsito mediano e p90 (dias entre saída e entrada); sem entrada há mais de 15 dias (e valor); compra potencialmente evitável (valor e % das compras de fornecedor). O filtro de filial vale para quem enviou OU recebeu — então o usuário com poucas filiais vê transferências que chegam de filiais que ele não alcança.

Compra potencialmente evitável. Compra de fornecedor (PAINEL_ALMOX_OPERACOES_COMPRA, padrão 101,131) de um item numa filial quando outra filial tinha o item parado o mês todo (o menor entre o saldo do fim do mês anterior e o do fim do mês da compra, pela série de 12 meses do 385) e não comprou o item naquele mês (quem compra todo mês está usando o próprio estoque: sem essa trava a "TENDER 3300" do Paraguai saía evitável todo mês, 23,9% → 9,1%). Valor = min(comprado, parado) × preço da compra. É um ponto de partida para transferir em vez de comprar. Imobilizado fora.

"Não localizadas": cartão próprio com todas as saídas sem entrada (inclusive as sem destino), com filtro de origem, destino e situação e o total filtrado; abre filtrado pelo indicador, pelo clique num fluxo e pelos números da grade por filial. Na tela vão 500 linhas por vez; o XLS traz todas.

Tempo: leva até ~1 min (26–38 s medidos) porque usa a apuração de saldos do 385.

E

Regras, travas e avisos

O que recusa e o que surpreende

Os três só leem. Sem regra de acesso nomeada; o alcance é pelas filiais do usuário. A coluna da direita diz a qual opção a regra pertence.

Bloqueia

O usuário não tem filial liberada.

QuandoUsuário sem nenhuma filial no alcance.

385 · 38D · 38E
Bloqueia

A filial N não está entre as filiais do usuário.

385 focoA filial N não está no recorte do painel. — o seletor de filial do painel pede uma filial fora do recorte.

385 · 38D · 38E
Bloqueia

Falta a cotação de <moeda> em dd/MM/aaaa: escolha outra data-base ou a moeda original.

QuandoMoeda de conversão escolhida sem cotação na data-base (fim do último mês). Em central não há cotação de dólar desde 2022: a conversão do 385 recusa.

Meses anterioresSem cotação num mês anterior não recusa: aviso Falta a cotação de <moeda> em <data>: o valor em estoque desse mês sai em branco.

385
Bloqueia

Não foram encontrados dados nessas condições.

38DNenhuma sobra, falta nem lançamento manual no período e filtros (a checagem é sobre a consulta de ajustes; vale para a tela e para o XLS).

38ENenhuma saída de transferência no período na empresa inteira (a checagem é antes do filtro de filial).

38D · 38E
Bloqueia

Faltam os tipos de transferência em PAINEL_ALMOX_TIPOS_TRANSF_SAIDA / PAINEL_ALMOX_TIPOS_TRANSF_ENTRADA (Config. Globais).

QuandoUma das duas chaves ficou vazia (sem o padrão).

38E
Aviso

N item(ns) com saldo e sem nenhuma entrada com valor: entram com valor zero.

EfeitoO valor em estoque do item é zero; o saldo e a cobertura continuam.

385
Aviso

Nenhum tipo de consumo em PAINEL_ALMOX_TIPOS_CONSUMO (Config. Globais): o consumo sai zerado.

EfeitoSem consumo, ninguém entra em ruptura/excesso; só PARADO e o valor em estoque.

385
Aviso

N saída(s) de consumo sem cotação de <moeda> no dia: ficam fora do valor.

385
Aviso

N compra(s) de mais de 12 meses antes da data final ficam fora da compra potencialmente evitável (a série de saldos cobre 12 meses).

EfeitoPeríodo do 38E maior que 12 meses: as compras mais antigas não são avaliadas (mas já entraram no total de compras do percentual).

38E
Aviso

O estoque pode estar até 10 min atrasado.

EfeitoLançamento feito agora não aparece no 38D/38E (sem Atualizar) e no 385 só após Atualizar. Cada usuário tem a sua apuração.

385 · 38D · 38E
Aviso

O estoque segue a view do inventário (3332), não a regra da CAN.

EfeitoEstoque do 385/38D/38E pode divergir do saldo do 24D/CAN (SaldoAlmoxarifado) nos tipos 1178/11115. O custo em moeda 111 não é arredondado a 0 casas como o custo_almox_si do legado (aquele arredondamento foi tratado como defeito e não reproduzido): diferença de centavos por unidade contra o 3332.

385 · 38D · 38E
Aviso

Restore de homologação pode deixar a view como esqueleto.

EfeitoEm 03/10/2026, o restore deixou almoxarifado_movimentacao_analitica como select 1 AS idserver, ... (1 linha): 385, a parte de estoque do 38D, a compra evitável do 38E e o 3332 saíram zerados até a view ser recriada. Antes de abrir defeito de "estoque zero", confira a view.

385 · 38D · 38E
Aviso

Juruena (12) com estoque zero é real.

MotivoA soma das movimentações da filial na view é exatamente 0 desde maio/2026 (R$ 5,6 mi em março, R$ 1,3 mi em abril): filial esvaziada.

385 · 38D
F

Configuração e permissões

Config. Globais (grupo faturamento)

Listas de ids separadas por vírgula, ponto e vírgula ou espaço em system_config.valor_string. Chave vazia usa o padrão.

ChavePadrãoQuem usaEfeito
PAINEL_ALMOX_TIPOS_CONSUMO117385Tipos de saída que são consumo.
PAINEL_ALMOX_COBERTURA_MIN15385Cobertura em dias abaixo da qual há ruptura (sem mínimo no cadastro) e a cobertura da ABC é "baixa".
PAINEL_ALMOX_COBERTURA_MAX180385Teto em dias do excesso (sem máximo no cadastro) e cobertura "alta" da ABC.
PAINEL_ALMOX_OPERACOES_COMPRA101,13138E (e 389)tipo_faturamento.tipo_operacao da compra de fornecedor (101 insumos, 131 serviços). Fora: 171 transferência, 311 retorno, 551 ajuste, 501 cancelamento, 111 manutenção de imobilizado, 121 compra de imobilizado.
PAINEL_ALMOX_TIPOS_AJUSTE_SOBRA / _FALTA11187 / 1118838DTipos de compra (sobra) e de saída (falta) do inventário.
PAINEL_ALMOX_TIPOS_TRANSF_SAIDA / _ENTRADA1151 / 115238ETipos da transferência.

Permissão. Item de menu sem idOpcao: qualquer usuário logado abre. O alcance é o das filiais do usuário (FiliaisDoUsuario). Barra de filtros salvos por usuário (códigos 385, 38D, 38E).

Código fixo no SQL (regra chumbada por id): o custo de entrada do 385 ignora a compra de tipo 1158 (ac.idtipo_faturamento <> 1158) sem chave de configuração.

G

Casos de teste sugeridos

Com o resultado esperado e como conferir no banco

Banco: central (BMG, view almoxarifado_movimentacao_analitica funcionando: 1,17 mi de linhas em 04/10/2026). Referências de 03–04/10/2026.

#OpçãoPassoEsperadoComo conferir
1385Data-base 03/10/2026, janela 90, todas as filiais, moeda local, "Ver em tela".Ordem de grandeza (medição de 03/10, antes das correções do custo): R$ ≈ 30,8 mi em estoque; ≈ 9,1 mil itens com saldo; consumo ≈ R$ 27,9 mi; ≈ 2,6 mil em ruptura (cobertura < 15 dias), ≈ 701 em excesso, ≈ 6,5 mil parados (≈ R$ 15,8 mi). Depois das correções o estoque de 30/09 foi R$ ≈ 28,0 mi (38D). ~15 s.Os totais mudam com lançamentos novos; confira um item (caso 2) em vez do total.
2385Abrir um item (lista de Ruptura/Excesso/Parado) e conferir saldo, consumo e custo.Saldo = soma da view até a data-base; consumo = soma dos tipos 117 na janela; custo = último custo de entrada da filial. (Farelo de soja de Entre Rios em 03/10: saldo 19.810,90 e consumo R$ 4.489.914,94 em 90 dias.)
-- saldo de um item numa filial na data-base (a mesma view do inventário 3332)
SELECT ROUND(SUM(ama.quantidade), 3) AS saldo
FROM almoxarifado_movimentacao_analitica ama
JOIN almoxarifado_produto ap ON ap.id = ama.idalmoxarifado_produto AND COALESCE(ap.imobilizado,'F') <> 'T'
WHERE ama.idfilial = <filial> AND ama.idalmoxarifado_produto = <produto>
  AND ama.data < DATE_ADD('2026-10-03', INTERVAL 1 DAY)
-- consumo na janela (90 dias até a data-base): quantidade e valor em moeda local
SELECT SUM(asp.quantidade) AS qtd, ROUND(SUM(asp.custo_total * IF(COALESCE(asp.idmoeda,0) IN (0, <idmoeda_local>), 1, asp.valor_cambio)), 2) AS valor
FROM almoxarifado_saida_produto asp
JOIN almoxarifado_saida s ON s.id = asp.idalmoxarifado_saida
WHERE asp.excluido <> 'T' AND COALESCE(s.excluido,'F') <> 'T'
  AND asp.idfilial = <filial> AND asp.idalmoxarifado_produto = <produto>
  AND s.idtipo_faturamento IN (117)                      -- PAINEL_ALMOX_TIPOS_CONSUMO
  AND s.data_emissao >= '2026-07-06' AND s.data_emissao < '2026-10-04'
-- último custo de entrada da FILIAL no produto (compra fora o tipo 1158 e de cabeçalho não excluído; ou lançamento manual de entrada)
SELECT ac.data_entrada, acp.valor_total_ml / acp.quantidade AS custo
FROM almoxarifado_compra_produto acp JOIN almoxarifado_compra ac ON ac.id = acp.idalmoxarifado_compra
WHERE acp.excluido <> 'T' AND ac.idtipo_faturamento <> 1158 AND acp.valor_total_ml > 0 AND acp.quantidade > 0
  AND acp.idfilial = <filial> AND acp.idalmoxarifado_produto = <produto>
ORDER BY ac.data_entrada DESC LIMIT 3
3385Colorado (10) em 31/07/2026, imobilizado fora.Valor em estoque ≈ R$ 961.623,71 (antes da correção dava R$ 10,69 mi por usar o custo da empresa: a serra 1011827 com duas entradas manuais de R$ 36.500 na filial 12).O 3332 de quem testou deu R$ 985.105,71; recalculado pela view + custo_almox_si: R$ 986.772,03 com imobilizado (R$ 22,3 mil) e R$ 964.486,39 sem. A diferença de ~R$ 2,9 mil para o painel é o custo_almox_si arredondando a 0 casas quando a moeda é a 111.
4385Item com mínimo 1 e máximo 2 no cadastro e consumo diário alto.Classificado pela cobertura em dias, não pelo par.SELECT estoque_minimo, estoque_maximo FROM almoxarifado_produto WHERE id = <produto>
5385Clicar num mês do gráfico de valor, em qualquer ponto; depois "ver faixas sem saída".O cartão lateral troca pelo valor de todas as filiais do mês (maior em cima); o botão/mesmo mês volta às faixas.Soma das filiais do mês = ponto do gráfico "todas".
6385Aba ABC: escolher uma filial no seletor.A classe é recalculada só com os itens da filial; a lista da célula e o consumo por setor seguem o foco.A=80% do consumo em valor da filial.
7385Fora do Brasil (fjfrigo_concepcion), 31/08/2025, 90 dias: dólar e depois moeda local.Estoque ≈ U$ 5.824.129,73 × 42.673.398.427,69 G$ (≈ 7.327 G$/U$); a cobertura muda (65 → 68 dias: consumo converte pelo dia, estoque pelo fim do mês). A base de concepcion para em 24/08.moeda_valores do dólar em 31/08/2025 e dias do consumo.
8385No central, converter para dólar.Recusa Falta a cotação de ....SELECT MAX(data) FROM moeda_valores WHERE idmoeda = 112
938D01/10/2025 a 30/09/2026, todas as filiais.Sobras ≈ R$ 6.919.324,81; faltas ≈ R$ 10.154.798,92; líquido ≈ −R$ 3,24 mi; bruto ≈ R$ 17,07 mi; ≈ 6.337 itens ajustados; ≈ 1.046 recorrentes; ≈ 7.811 linhas por 2 usuários. Juruena (12): R$ 2,0 mi de sobra e R$ 4,5 mi de falta, 479 recorrentes. Embalagens ≈ R$ 12 mi do bruto.
SELECT ROUND(SUM(cp.valor_total_ml), 2) AS sobras, COUNT(*) AS linhas
FROM almoxarifado_compra ac
JOIN almoxarifado_compra_produto cp ON cp.idalmoxarifado_compra = ac.id AND cp.excluido <> 'T'
JOIN almoxarifado_produto ap ON ap.id = cp.idalmoxarifado_produto AND COALESCE(ap.imobilizado,'F') <> 'T'
WHERE COALESCE(ac.excluido,'F') <> 'T' AND ac.idtipo_faturamento IN (11187)   -- PAINEL_ALMOX_TIPOS_AJUSTE_SOBRA
  AND ac.data_entrada >= '2025-10-01' AND ac.data_entrada < '2026-10-01'
-- 04/10/2026, central: R$ 6.919.324,81 (3.283 linhas)
SELECT ROUND(SUM(asp.custo_total * IF(COALESCE(asp.idmoeda,0) IN (0, <idmoeda_local>), 1, asp.valor_cambio)), 2) AS faltas, COUNT(*) AS linhas
FROM almoxarifado_saida s
JOIN almoxarifado_saida_produto asp ON asp.idalmoxarifado_saida = s.id AND asp.excluido <> 'T'
JOIN almoxarifado_produto ap ON ap.id = asp.idalmoxarifado_produto AND COALESCE(ap.imobilizado,'F') <> 'T'
WHERE COALESCE(s.excluido,'F') <> 'T' AND s.idtipo_faturamento IN (11188)     -- PAINEL_ALMOX_TIPOS_AJUSTE_FALTA
  AND s.data_emissao >= '2025-10-01' AND s.data_emissao < '2026-10-01'
-- 04/10/2026, central: R$ 10.154.798,92 (4.528 linhas)
1038DMesmo caso: % dos itens com saldo.Estoque na data final ≈ R$ 28,0 mi; ajuste bruto ≈ 61% do estoque; itens ajustados ≈ 69,6% dos 9.108 itens com saldo.O estoque vem do 385 na data final.
1138DQuadro dos lançamentos manuais.Por operação e justificativa, fora da taxa; muitos sem justificativa.SELECT tipo_operacao, COUNT(*), SUM(COALESCE(NULLIF(valor_ml,0), valor)) FROM almoxarifado_lancamentos_manuais WHERE excluido <> 'T' AND data >= '2025-10-01' GROUP BY 1
1238Dfjfrigo_concepcion.Sem nenhum 11187/11188 (sobras e faltas zeradas); estoque ≈ 42,7 bi G$, 9.642 itens com saldo, 10 negativos (~38 s).—
1338E01/10/2025 a 30/09/2026 no central.Cerca de 2,5 mil saídas (R$ ≈ 59,8 mi); entrada localizada em ≈ 50,5%; trânsito mediano 5 dias (p90 20); ≈ R$ 20,9 mi sem entrada; ≈ 1.226 não localizadas (1.213 sem entrada + 13 sem destino); compra evitável ≈ R$ 20,3 mi (≈ 9,5% das compras). Entre Rios → Margarida: 694 saídas, 457 sem entrada.
SELECT s.id, s.idfilial AS origem, s.documento, s.data_emissao, e.id AS entrada_id, e.idfilial AS destino, e.data_entrada
FROM almoxarifado_saida s
LEFT JOIN almoxarifado_compra e ON e.idalmoxarifado_saida = s.id AND e.idtipo_faturamento IN (1152)   -- ligação direta (Paraguai)
WHERE COALESCE(s.excluido,'F') <> 'T' AND s.idtipo_faturamento IN (1151)                              -- PAINEL_ALMOX_TIPOS_TRANSF_SAIDA
  AND s.data_emissao >= '2025-10-01' AND s.data_emissao < '2026-10-01'
-- no central a ligação direta está vazia: o destino sai do CNPJ do emitente (filial.cnpj = emitente.cnpj_cpf, sem pontuação)
-- e a entrada é a 1152 do destino com o mesmo documento (sem zeros à esquerda), de -5 a +180 dias da saída
-- compras de fornecedor do mês, base da "compra potencialmente evitável"
SELECT cp.idfilial, cp.idalmoxarifado_produto, DATE_FORMAT(ac.data_entrada,'%Y-%m') AS mes, SUM(cp.quantidade) AS q, SUM(cp.valor_total_ml) AS v
FROM almoxarifado_compra_produto cp
JOIN almoxarifado_compra ac ON ac.id = cp.idalmoxarifado_compra
JOIN tipo_faturamento tf ON tf.id = ac.idtipo_faturamento AND tf.tipo_operacao IN ('101','131')   -- PAINEL_ALMOX_OPERACOES_COMPRA
WHERE cp.excluido <> 'T' AND COALESCE(ac.excluido,'F') <> 'T' AND cp.quantidade > 0 AND cp.valor_total_ml > 0
GROUP BY 1, 2, 3
-- depois: para cada compra, o saldo parado das OUTRAS filiais no mês (min entre fim do mês anterior e fim do mês da compra),
-- só de filiais que não compraram o item naquele mês; evitável = min(comprado, parado) x preço da compra
1438EAba "Não localizadas": filtrar origem, destino e situação.Lista as sem entrada e as sem destino; limpar filtros volta; mostra "N de T" e total filtrado; o XLS traz todas.—
1538Efjfrigo_concepcion, 09/2024 a 08/2025.787 saídas, 37,1 bi G$, 100% com entrada (ligação direta), trânsito mediano 1 dia; compra evitável ≈ 19,1 bi G$ (9,1%). ~38 s.almoxarifado_compra.idalmoxarifado_saida preenchido.
1638EPeríodo de 18 meses.Aviso das compras com mais de 12 meses fora da compra evitável.—
17385·38D·38ELançar um ajuste/entrada agora e reabrir o 38D ou 38E sem esperar.Não aparece por até 10 min; no 385, Atualizar mostra na hora.Aguardar 10 min.
H

Limitações, pendências e achados

O que ainda não existe ou merece atenção

Pendências: teste de tela dos três (backend precisa reiniciar) e reconferência do 385 depois das correções de 03/10 (custo da filial, saldo pela view do 3332, foco por filial, dólar fora do Brasil); o 38E depende do build do tenant para ligar saída e entrada.

Não dá para medir: acuracidade clássica (itens contados sem divergência) — não há contagem gravada.

Ruptura por cobertura conta o item C comprado sob demanda (saldo zero com consumo esporádico): 1.863 produtos C na célula C × baixa em central.

Achados ao ler o código (não corrigidos)

1. 38D — % de itens ajustados. Numerador = todos os pares filial × produto ajustados no período; denominador = itens com saldo > 0 só na data final. Item ajustado que hoje tem saldo zero infla o percentual (pode passar de 100%).

2. 385 — custo sem filtro de cabeçalho excluído. A consulta de custo (custos()) filtra acp.excluido <> 'T' mas não almoxarifado_compra.excluido: uma entrada de compra com cabeçalho excluído pode virar o "último custo" (a view do saldo já ignora cabeçalho excluído). Os outros relatórios (389, 38D, 38E, 383) filtram o cabeçalho. Corrigido em 04/10/2026: custos() filtra COALESCE(ac.excluido,'F') <> 'T' (38D e 38E usam a mesma apuração). Itens vivos sob cabeçalho excluído: 41 no central (1 era o último custo da filial), 16 no fjfrigo_concepcion.

3. 385 — tipo 1158 chumbado (<> 1158) sem chave na Config. Globais; conferir se o id existe e significa o mesmo em cada tenant.

4. 38E — denominador do % evitável. compras soma o valor de todas as compras do período antes de descartar as de mais de 12 meses (fora da série), então o percentual fica subestimado quando o período passa de 12 meses (o aviso existe).

5. 38E — saídas de filiais fora do alcance. A consulta traz as transferências de toda a empresa e filtra por filial depois; o usuário vê saída de filial que ele não alcança quando o destino é dele (por desenho: "enviou OU recebeu").

I

Como o erro chega na tela

Para o QA reproduzir e reportar

Toda resposta sai com HTTP 200; quem diz o que aconteceu é o statuscode no corpo — 400 para as recusas deste documento.

O arquivo é pedido como download, mas a recusa chega como mensagem: a tela mostra a frase no lugar do arquivo. Enquanto gera, o botão mostra o contador Gerando… (Ns).

Avisos (cotação faltando, foto sem produção, estorno sem nota...) não interrompem: vêm no cabeçalho X-Aviso-Sistema e a tela mostra o painel de avisos. Teste sempre olhando o painel, não só o arquivo.

Ao abrir chamado, copie o código de ocorrência de 8 caracteres dos erros inesperados. Erro de tela vai para o log em POST /cadastro/erros-front.

Nenhuma regra bate com essa busca. Tente um trecho menor da mensagem, ou limpe os filtros.