229 lines
7.9 KiB
TypeScript
229 lines
7.9 KiB
TypeScript
|
|
import { useState, useEffect } from 'react';
|
|
import { supabase } from '@/integrations/supabase/client';
|
|
import { getSystemDateString, getDateOffsetString } from '@/utils/dateTimeUtils';
|
|
|
|
interface ApontamentoDiarioData {
|
|
ofNumber: string;
|
|
processo: string;
|
|
peso: number;
|
|
percentage: number;
|
|
}
|
|
|
|
interface ProcessoData {
|
|
processo: string;
|
|
total: number;
|
|
ofs: ApontamentoDiarioData[];
|
|
}
|
|
|
|
type PeriodoType = 'diario' | 'ultimos7' | 'ultimos15' | 'ultimos30' | 'projecao7';
|
|
|
|
interface ChartDataResult {
|
|
data: ProcessoData[];
|
|
effectiveDate: string;
|
|
}
|
|
|
|
export const useApontamentoDiarioChart = (periodo: PeriodoType) => {
|
|
const [result, setResult] = useState<ChartDataResult>({ data: [], effectiveDate: '' });
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const fetchData = async () => {
|
|
setLoading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
console.log('=== INICIANDO BUSCA DE DADOS PARA GRÁFICO DIÁRIO ===');
|
|
console.log('Período selecionado:', periodo);
|
|
|
|
// Calcular datas baseadas no período usando o utilitário de data do sistema
|
|
const hoje = getSystemDateString();
|
|
let dataInicio: string;
|
|
let dataFim: string = hoje;
|
|
let effectiveDate: string;
|
|
|
|
console.log('Data atual do sistema (hoje):', hoje);
|
|
|
|
switch (periodo) {
|
|
case 'diario':
|
|
// Para o período diário, usar a data atual (hoje) como data efetiva
|
|
dataInicio = hoje;
|
|
dataFim = hoje;
|
|
effectiveDate = hoje;
|
|
console.log('Modo diário - usando data atual:', effectiveDate);
|
|
break;
|
|
case 'ultimos7':
|
|
dataInicio = getDateOffsetString(-7);
|
|
effectiveDate = hoje;
|
|
break;
|
|
case 'ultimos15':
|
|
dataInicio = getDateOffsetString(-15);
|
|
effectiveDate = hoje;
|
|
break;
|
|
case 'ultimos30':
|
|
dataInicio = getDateOffsetString(-30);
|
|
effectiveDate = hoje;
|
|
break;
|
|
case 'projecao7':
|
|
// Para projeção, pegar dados dos últimos 14 dias para calcular média
|
|
dataInicio = getDateOffsetString(-14);
|
|
effectiveDate = hoje;
|
|
break;
|
|
default:
|
|
dataInicio = getDateOffsetString(-30);
|
|
effectiveDate = hoje;
|
|
}
|
|
|
|
console.log('Data início:', dataInicio);
|
|
console.log('Data fim:', dataFim);
|
|
console.log('Data efetiva para relatório:', effectiveDate);
|
|
|
|
// Consultar apontamentos com joins para obter pesos
|
|
const { data: apontamentos, error: apontamentosError } = await supabase
|
|
.from('apontamentos_producao')
|
|
.select(`
|
|
of_number,
|
|
data_apontamento,
|
|
quantidade_produzida,
|
|
tipo_apontamento,
|
|
processo:processos_fabricacao(nome, ordem),
|
|
peca:pecas(peso_unitario),
|
|
componente:componentes_peca(peso_unitario)
|
|
`)
|
|
.gte('data_apontamento', dataInicio)
|
|
.lte('data_apontamento', dataFim)
|
|
.order('of_number')
|
|
.order('data_apontamento');
|
|
|
|
if (apontamentosError) {
|
|
throw apontamentosError;
|
|
}
|
|
|
|
console.log('Apontamentos encontrados:', apontamentos?.length || 0);
|
|
console.log('Dados por OF:', apontamentos?.reduce((acc, apt) => {
|
|
acc[apt.of_number] = (acc[apt.of_number] || 0) + 1;
|
|
return acc;
|
|
}, {} as Record<string, number>));
|
|
|
|
if (!apontamentos || apontamentos.length === 0) {
|
|
console.log('Nenhum apontamento encontrado para o período');
|
|
setResult({ data: [], effectiveDate });
|
|
return;
|
|
}
|
|
|
|
// Processar dados agrupando por OF e processo
|
|
const dadosProcessados = new Map<string, Map<string, number>>();
|
|
|
|
apontamentos.forEach(apontamento => {
|
|
const ofNumber = apontamento.of_number;
|
|
const processoNome = apontamento.processo?.nome || 'Processo Desconhecido';
|
|
|
|
// Calcular peso baseado no tipo de apontamento
|
|
let pesoUnitario = 0;
|
|
if (apontamento.tipo_apontamento === 'componente' && apontamento.componente?.peso_unitario) {
|
|
pesoUnitario = Number(apontamento.componente.peso_unitario);
|
|
} else if (apontamento.tipo_apontamento === 'peca' && apontamento.peca?.peso_unitario) {
|
|
pesoUnitario = Number(apontamento.peca.peso_unitario);
|
|
}
|
|
|
|
let pesoTotal = pesoUnitario * Number(apontamento.quantidade_produzida);
|
|
|
|
// Para projeção, calcular média diária e multiplicar por 7
|
|
if (periodo === 'projecao7') {
|
|
const diasPeriodo = Math.ceil((new Date(dataFim).getTime() - new Date(dataInicio).getTime()) / (1000 * 60 * 60 * 24));
|
|
pesoTotal = (pesoTotal / diasPeriodo) * 7;
|
|
}
|
|
|
|
// Inicializar mapas se não existirem
|
|
if (!dadosProcessados.has(processoNome)) {
|
|
dadosProcessados.set(processoNome, new Map());
|
|
}
|
|
|
|
const processoMap = dadosProcessados.get(processoNome)!;
|
|
const pesoAtual = processoMap.get(ofNumber) || 0;
|
|
processoMap.set(ofNumber, pesoAtual + pesoTotal);
|
|
|
|
console.log(`OF ${ofNumber} - Processo ${processoNome}: +${pesoTotal.toFixed(2)} kg`);
|
|
});
|
|
|
|
// Converter para formato do gráfico
|
|
const processosOrdenados = ['Detalhamento', 'Corte', 'Solda', 'Pintura/Galv', 'Expedição', 'Montagem', 'Aceite/DB', 'Concluído'];
|
|
const processedData: ProcessoData[] = [];
|
|
|
|
processosOrdenados.forEach(processoNome => {
|
|
const processoData = dadosProcessados.get(processoNome);
|
|
if (processoData && processoData.size > 0) {
|
|
const ofsData: ApontamentoDiarioData[] = [];
|
|
let totalProcesso = 0;
|
|
|
|
// Converter Map para array e calcular total
|
|
for (const [ofNumber, peso] of processoData) {
|
|
if (peso > 0) {
|
|
ofsData.push({
|
|
ofNumber,
|
|
processo: processoNome,
|
|
peso: Math.round(peso),
|
|
percentage: 0 // Será calculado após somar o total
|
|
});
|
|
totalProcesso += peso;
|
|
}
|
|
}
|
|
|
|
// Calcular percentuais
|
|
ofsData.forEach(ofData => {
|
|
ofData.percentage = totalProcesso > 0 ? (ofData.peso / totalProcesso) * 100 : 0;
|
|
});
|
|
|
|
// Ordenar por OF
|
|
ofsData.sort((a, b) => a.ofNumber.localeCompare(b.ofNumber));
|
|
|
|
processedData.push({
|
|
processo: processoNome === 'Detalhamento' ? 'DETALH.' :
|
|
processoNome === 'Pintura/Galv' ? 'PINT/GALV.' :
|
|
processoNome === 'Expedição' ? 'EXPED.' :
|
|
processoNome === 'Montagem' ? 'MONTAG.' :
|
|
processoNome === 'Aceite/DB' ? 'ACEITE/DB' :
|
|
processoNome === 'Concluído' ? 'CONCLUÍDO' :
|
|
processoNome.toUpperCase(),
|
|
total: Math.round(totalProcesso),
|
|
ofs: ofsData
|
|
});
|
|
|
|
console.log(`Processo ${processoNome}: ${Math.round(totalProcesso)} kg total, ${ofsData.length} OFs`);
|
|
}
|
|
});
|
|
|
|
console.log('=== RESULTADO FINAL ===');
|
|
console.log('Processos com dados:', processedData.length);
|
|
console.log('Data efetiva:', effectiveDate);
|
|
console.log('OFs únicas no período:', [...new Set(apontamentos.map(apt => apt.of_number))]);
|
|
processedData.forEach(item => {
|
|
console.log(`${item.processo}: ${item.total} kg (${item.ofs.length} OFs)`);
|
|
item.ofs.forEach(ofData => {
|
|
console.log(` - OF ${ofData.ofNumber}: ${ofData.peso} kg`);
|
|
});
|
|
});
|
|
|
|
setResult({ data: processedData, effectiveDate });
|
|
|
|
} catch (error) {
|
|
console.error('Erro ao buscar dados do gráfico:', error);
|
|
setError('Erro ao carregar dados do gráfico');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, [periodo]);
|
|
|
|
return {
|
|
data: result.data,
|
|
effectiveDate: result.effectiveDate,
|
|
loading,
|
|
error,
|
|
refetch: fetchData
|
|
};
|
|
};
|