import { useState, useCallback } from 'react'; import { supabase } from '@/integrations/supabase/client'; import { naturalSort } from '@/utils/naturalSort'; export interface InconsistenciaItem { marca: string; tipo: string; descricao: string; detalhes: Record; acaoSugerida?: string; } export interface ResultadoAuditoria { inconsistencias: { processos: InconsistenciaItem[]; quantidades: InconsistenciaItem[]; expedicao: InconsistenciaItem[]; prioridades: InconsistenciaItem[]; estoque: InconsistenciaItem[]; }; verificacoesRealizadas: string[]; dataVerificacao: Date; } export const useAuditoriaInconsistencias = () => { const [data, setData] = useState(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!apontamentos_producao_processo_id_fkey(nome, ordem), peca:pecas!apontamentos_producao_peca_id_fkey(marca, etapa_fase, quantidade), componente:componentes_peca!apontamentos_producao_componente_id_fkey(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); // 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>); 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(key => { const categoria = key as keyof typeof inconsistencias; inconsistencias[categoria].sort((a: InconsistenciaItem, b: InconsistenciaItem) => 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 }; };