🚀 Initial commit: Versão atual do TrackSteel APP

This commit is contained in:
2026-03-18 21:17:53 +00:00
commit bde410c9ad
633 changed files with 108150 additions and 0 deletions
+288
View File
@@ -0,0 +1,288 @@
import { useState, useCallback } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { naturalSort } from '@/utils/naturalSort';
interface InconsistenciaItem {
marca: string;
tipo: string;
descricao: string;
detalhes: any;
acaoSugerida?: string;
}
interface ResultadoAuditoria {
inconsistencias: {
processos: InconsistenciaItem[];
quantidades: InconsistenciaItem[];
expedicao: InconsistenciaItem[];
prioridades: InconsistenciaItem[];
estoque: InconsistenciaItem[];
};
verificacoesRealizadas: string[];
dataVerificacao: Date;
}
export const useAuditoriaInconsistencias = () => {
const [data, setData] = useState<ResultadoAuditoria | null>(null);
const [loading, setLoading] = useState(false);
const executarAuditoria = useCallback(async (ofNumber: string, processo?: string, faseOF?: string) => {
setLoading(true);
try {
console.log(`🔍 Iniciando auditoria para OF: ${ofNumber}, Processo: ${processo || 'todos'}, Fase: ${faseOF || 'todas'}`);
// Buscar dados necessários
const [pecasData, apontamentosData, romaneiosData, prioridadesData, processosData] = await Promise.all([
// Peças da OF filtradas por fase se especificada
supabase
.from('pecas')
.select('*')
.eq('of_number', ofNumber)
.then(({ data }) => {
if (!data) return [];
return faseOF ? data.filter(p => p.etapa_fase === faseOF) : data;
}),
// Apontamentos de produção
supabase
.from('apontamentos_producao')
.select(`
*,
processo:processos_fabricacao(nome, ordem),
peca:pecas(marca, etapa_fase, quantidade),
componente:componentes_peca(marca_componente)
`)
.eq('of_number', ofNumber)
.then(({ data }) => data || []),
// Romaneios de expedição
supabase
.from('itens_romaneio_pecas')
.select(`
*,
romaneio:romaneios_expedicao!inner(of_number)
`)
.eq('romaneio.of_number', ofNumber)
.then(({ data }) => data || []),
// Prioridades de fabricação - buscar corretamente as peças em prioridades
supabase
.from('itens_prioridade_fabricacao')
.select(`
*,
peca:pecas!inner(of_number, marca, etapa_fase),
prioridade_fabricacao:prioridades_fabricacao!inner(
of_number,
etapa_fase,
prioridade_config:prioridades_config(codigo, nome)
)
`)
.eq('peca.of_number', ofNumber)
.then(({ data }) => {
if (!data) return [];
return faseOF ? data.filter(item => item.peca?.etapa_fase === faseOF) : data;
}),
// Processos de fabricação
supabase
.from('processos_fabricacao')
.select('*')
.order('ordem')
.then(({ data }) => data || [])
]);
// Filtrar apontamentos por fase da OF se especificada
const apontamentosFiltrados = faseOF ?
apontamentosData.filter(a => a.peca?.etapa_fase === faseOF) :
apontamentosData;
// Filtrar por processo se especificado
const apontamentosProcessoFiltrados = processo ?
apontamentosFiltrados.filter(a => a.processo?.nome === processo) :
apontamentosFiltrados;
const inconsistencias: ResultadoAuditoria['inconsistencias'] = {
processos: [],
quantidades: [],
expedicao: [],
prioridades: [],
estoque: []
};
// 1. Verificar sequência de processos
pecasData.forEach(peca => {
const apontamentosPeca = apontamentosProcessoFiltrados.filter(a =>
a.tipo_apontamento === 'peca' && a.peca?.marca === peca.marca
);
// Ordenar apontamentos por ordem do processo
const apontamentosOrdenados = apontamentosPeca
.filter(a => a.processo?.ordem)
.sort((a, b) => a.processo.ordem - b.processo.ordem);
// Verificar se há processos pulados
for (let i = 1; i < apontamentosOrdenados.length; i++) {
const ordemAnterior = apontamentosOrdenados[i - 1].processo.ordem;
const ordemAtual = apontamentosOrdenados[i].processo.ordem;
if (ordemAtual - ordemAnterior > 1) {
// Verificar se a peça tem componentes para determinar se deve passar pela solda
const devePassarPelaSolda = peca.tem_componentes;
const processosPulados = [];
for (let ordem = ordemAnterior + 1; ordem < ordemAtual; ordem++) {
const processoEncontrado = processosData.find(p => p.ordem === ordem);
if (processoEncontrado) {
// Se não tem componentes e o processo é solda, não é inconsistência
if (!devePassarPelaSolda && processoEncontrado.nome.toLowerCase().includes('solda')) {
continue;
}
processosPulados.push(processoEncontrado.nome);
}
}
if (processosPulados.length > 0) {
inconsistencias.processos.push({
marca: peca.marca,
tipo: 'Processo Pulado',
descricao: `Peça pulou processo(s): ${processosPulados.join(', ')}`,
detalhes: {
processosPulados,
apontamentos: apontamentosOrdenados.map(a => ({
processo: a.processo.nome,
data: a.data_apontamento,
quantidade: a.quantidade_produzida
}))
},
acaoSugerida: 'Verificar se os processos intermediários foram executados'
});
}
}
}
});
// 2. Verificar quantidades inconsistentes
pecasData.forEach(peca => {
const apontamentosPeca = apontamentosProcessoFiltrados.filter(a =>
a.tipo_apontamento === 'peca' && a.peca?.marca === peca.marca
);
// Agrupar por processo
const quantidadesPorProcesso = apontamentosPeca.reduce((acc, apt) => {
const processo = apt.processo?.nome || 'Desconhecido';
acc[processo] = (acc[processo] || 0) + apt.quantidade_produzida;
return acc;
}, {} as Record<string, number>);
// Verificar se algum processo tem mais quantidade que o cadastrado
Object.entries(quantidadesPorProcesso).forEach(([processo, quantidade]) => {
if (quantidade > peca.quantidade) {
inconsistencias.quantidades.push({
marca: peca.marca,
tipo: 'Quantidade Excedente',
descricao: `Processo ${processo} tem ${quantidade} peças apontadas, mas cadastro tem ${peca.quantidade}`,
detalhes: {
quantidadeCadastrada: peca.quantidade,
quantidadeApontada: quantidade,
processo,
diferenca: quantidade - peca.quantidade
},
acaoSugerida: 'Verificar apontamentos duplicados ou corrigir quantidade no cadastro'
});
}
});
});
// 3. Verificar peças expedidas sem processos anteriores
const pecasExpedidas = romaneiosData.map(r => r.marca);
const pecasComProcessos = [...new Set(apontamentosProcessoFiltrados.map(a => a.peca?.marca).filter(Boolean))];
pecasExpedidas.forEach(marca => {
if (!pecasComProcessos.includes(marca)) {
const peca = pecasData.find(p => p.marca === marca);
if (peca) {
inconsistencias.expedicao.push({
marca,
tipo: 'Expedição sem Processos',
descricao: 'Peça expedida sem nenhum processo de produção apontado',
detalhes: {
romaneios: romaneiosData.filter(r => r.marca === marca)
},
acaoSugerida: 'Apontar processos de produção antes da expedição'
});
}
}
});
// 4. Verificar peças em múltiplas prioridades DIFERENTES (P1, P2, P3, P4)
console.log('🔍 Verificando prioridades duplicadas para peças:', prioridadesData.length, 'itens encontrados');
const pecasEmPrioridades = prioridadesData.reduce((acc, item) => {
const marca = item.peca?.marca;
const codigoPrioridade = item.prioridade_fabricacao?.prioridade_config?.codigo;
if (marca && codigoPrioridade) {
if (!acc[marca]) acc[marca] = new Set();
acc[marca].add(codigoPrioridade);
}
return acc;
}, {} as Record<string, Set<string>>);
Object.entries(pecasEmPrioridades).forEach(([marca, prioridades]) => {
if (prioridades.size > 1) {
const prioridadesArray = Array.from(prioridades);
inconsistencias.prioridades.push({
marca,
tipo: 'Múltiplas Prioridades',
descricao: `Peça está em ${prioridades.size} prioridades diferentes: ${prioridadesArray.join(', ')}`,
detalhes: {
prioridades: prioridadesArray,
detalhes: prioridadesData
.filter(item => item.peca?.marca === marca)
.map(item => ({
prioridade: item.prioridade_fabricacao?.prioridade_config?.codigo,
nome_prioridade: item.prioridade_fabricacao?.prioridade_config?.nome,
quantidade: item.quantidade_priorizada
}))
},
acaoSugerida: 'Remover peça das prioridades desnecessárias, mantendo apenas em uma'
});
}
});
// Aplicar ordenação natural
Object.keys(inconsistencias).forEach(categoria => {
(inconsistencias as any)[categoria].sort((a: any, b: any) => naturalSort(a.marca, b.marca));
});
const resultado: ResultadoAuditoria = {
inconsistencias,
verificacoesRealizadas: [
'Sequência de processos de produção',
'Consistência de quantidades por processo',
'Peças expedidas sem processos anteriores',
'Peças em múltiplas prioridades de fabricação diferentes',
'Duplicação de apontamentos no mesmo processo'
],
dataVerificacao: new Date()
};
console.log(`✅ Auditoria concluída: ${Object.values(inconsistencias).reduce((total, cat) => total + cat.length, 0)} inconsistências encontradas`);
setData(resultado);
} catch (error) {
console.error('❌ Erro na auditoria:', error);
setData(null);
} finally {
setLoading(false);
}
}, []);
return {
data,
loading,
executarAuditoria
};
};