Adiciona percentual de progresso e data do ultimo apontamento no relatorio de pecas por processo

This commit is contained in:
2026-09-22 10:45:08 +00:00
parent 9574cdb3cb
commit 3a3e230ce7
4 changed files with 312 additions and 67 deletions
@@ -1,11 +1,12 @@
import React, { useState } from 'react';
import React, { useState, useMemo } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { X, FileText, Printer } from 'lucide-react';
import { useOFs } from '@/hooks/useOFs';
import { useRelatorioPecasProcesso, PecaComStatus } from '@/hooks/useRelatorioPecasProcesso';
import { useDashboardProducaoOtimizado } from '@/hooks/useDashboardProducaoOtimizado';
import { RelatorioPecasProcessoPDF } from './RelatorioPecasProcessoPDF';
import { RelatorioPecasProcessoPrint } from './RelatorioPecasProcessoPrint';
@@ -22,6 +23,7 @@ export const RelatorioPecasProcessoModal: React.FC<RelatorioPecasProcessoModalPr
const [selectedFase, setSelectedFase] = useState('todas');
const { ofs, loading: ofsLoading } = useOFs();
const { pecasComStatus, resumoProcessos, loading } = useRelatorioPecasProcesso(selectedOF);
const { dashboardData } = useDashboardProducaoOtimizado(selectedOF);
// Filtrar peças por fase selecionada
const pecasFiltradas = selectedFase === 'todas'
@@ -37,6 +39,33 @@ export const RelatorioPecasProcessoModal: React.FC<RelatorioPecasProcessoModalPr
pesoTotalExpedicao: pecasFiltradas.filter(p => p.processos.expedicao).reduce((sum, p) => sum + p.peso_total, 0)
};
// Calcular percentual de progresso conforme índices da tela de Dashboard de Produção
const percentuais = useMemo(() => {
if (selectedFase === 'todas' && dashboardData?.processos && dashboardData.processos.length > 0) {
const pCorte = dashboardData.processos.find(p => p.nome.toLowerCase().includes('corte'))?.progressoReal ?? 0;
const pSolda = dashboardData.processos.find(p => p.nome.toLowerCase().includes('solda'))?.progressoReal ?? 0;
const pPintura = dashboardData.processos.find(p => p.nome.toLowerCase().includes('pint') || p.nome.toLowerCase().includes('galv'))?.progressoReal ?? 0;
const pExp = dashboardData.processos.find(p => p.nome.toLowerCase().includes('exped'))?.progressoReal ?? 0;
return {
corte: pCorte,
solda: pSolda,
pintura: pPintura,
expedicao: pExp
};
}
const pesoTotalGeral = pecasFiltradas.reduce((sum, p) => sum + p.peso_total, 0);
const pesoTotalSoldavel = pecasFiltradas.filter(p => p.tem_componentes).reduce((sum, p) => sum + p.peso_total, 0) || pesoTotalGeral;
return {
corte: pesoTotalGeral > 0 ? (estatisticasFiltradas.pesoTotalCorte / pesoTotalGeral) * 100 : 0,
solda: pesoTotalSoldavel > 0 ? (estatisticasFiltradas.pesoTotalSolda / pesoTotalSoldavel) * 100 : 0,
pintura: pesoTotalGeral > 0 ? (estatisticasFiltradas.pesoTotalPintura / pesoTotalGeral) * 100 : 0,
expedicao: pesoTotalGeral > 0 ? (estatisticasFiltradas.pesoTotalExpedicao / pesoTotalGeral) * 100 : 0,
};
}, [selectedFase, dashboardData, pecasFiltradas, estatisticasFiltradas]);
// Obter fases únicas das peças
const fasesUnicas = [...new Set(pecasComStatus.map(peca => peca.etapa_fase))].sort((a, b) => {
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
@@ -95,12 +124,14 @@ export const RelatorioPecasProcessoModal: React.FC<RelatorioPecasProcessoModalPr
<RelatorioPecasProcessoPDF
pecasComStatus={pecasFiltradas}
estatisticas={estatisticasFiltradas}
percentuais={percentuais}
selectedOF={selectedOF}
selectedFase={selectedFase}
/>
<RelatorioPecasProcessoPrint
pecasComStatus={pecasFiltradas}
estatisticas={estatisticasFiltradas}
percentuais={percentuais}
selectedOF={selectedOF}
selectedFase={selectedFase}
/>
@@ -115,7 +146,7 @@ export const RelatorioPecasProcessoModal: React.FC<RelatorioPecasProcessoModalPr
Preview - OF {selectedOF} {selectedFase !== 'todas' ? `- Fase ${selectedFase}` : ''}
</h3>
{/* Estatísticas */}
{/* Estatísticas com Percentual de Progresso */}
<div className="grid grid-cols-2 md:grid-cols-5 gap-4 mb-6">
<div className="bg-muted/50 p-3 rounded text-center">
<p className="text-sm text-muted-foreground">Total de Peças</p>
@@ -123,19 +154,39 @@ export const RelatorioPecasProcessoModal: React.FC<RelatorioPecasProcessoModalPr
</div>
<div className="bg-muted/50 p-3 rounded text-center">
<p className="text-sm text-muted-foreground">Peso Corte</p>
<p className="text-xl font-bold text-card-foreground">{estatisticasFiltradas.pesoTotalCorte.toFixed(0)} kg</p>
<p className="text-xl font-bold text-card-foreground">
{estatisticasFiltradas.pesoTotalCorte.toFixed(0)} kg{' '}
<span className="text-sm font-semibold text-blue-600 dark:text-blue-400">
({percentuais.corte.toFixed(1)}%)
</span>
</p>
</div>
<div className="bg-muted/50 p-3 rounded text-center">
<p className="text-sm text-muted-foreground">Peso Solda</p>
<p className="text-xl font-bold text-card-foreground">{estatisticasFiltradas.pesoTotalSolda.toFixed(0)} kg</p>
<p className="text-xl font-bold text-card-foreground">
{estatisticasFiltradas.pesoTotalSolda.toFixed(0)} kg{' '}
<span className="text-sm font-semibold text-blue-600 dark:text-blue-400">
({percentuais.solda.toFixed(1)}%)
</span>
</p>
</div>
<div className="bg-muted/50 p-3 rounded text-center">
<p className="text-sm text-muted-foreground">Peso Pintura</p>
<p className="text-xl font-bold text-card-foreground">{estatisticasFiltradas.pesoTotalPintura.toFixed(0)} kg</p>
<p className="text-xl font-bold text-card-foreground">
{estatisticasFiltradas.pesoTotalPintura.toFixed(0)} kg{' '}
<span className="text-sm font-semibold text-blue-600 dark:text-blue-400">
({percentuais.pintura.toFixed(1)}%)
</span>
</p>
</div>
<div className="bg-muted/50 p-3 rounded text-center">
<p className="text-sm text-muted-foreground">Peso Expedição</p>
<p className="text-xl font-bold text-card-foreground">{estatisticasFiltradas.pesoTotalExpedicao.toFixed(0)} kg</p>
<p className="text-xl font-bold text-card-foreground">
{estatisticasFiltradas.pesoTotalExpedicao.toFixed(0)} kg{' '}
<span className="text-sm font-semibold text-blue-600 dark:text-blue-400">
({percentuais.expedicao.toFixed(1)}%)
</span>
</p>
</div>
</div>
@@ -161,21 +212,67 @@ export const RelatorioPecasProcessoModal: React.FC<RelatorioPecasProcessoModalPr
<tr key={`${peca.id}-${index}`} className="hover:bg-muted/20">
<td className="border border-border p-2 text-xs text-card-foreground">{peca.of_number}</td>
<td className="border border-border p-2 text-xs text-card-foreground">{peca.etapa_fase}</td>
<td className="border border-border p-2 text-xs text-card-foreground">{peca.marca}</td>
<td className="border border-border p-2 text-xs text-card-foreground font-semibold">{peca.marca}</td>
<td className="border border-border p-2 text-xs text-center text-card-foreground">{peca.quantidade}</td>
<td className="border border-border p-2 text-xs text-right text-card-foreground">{peca.peso_unitario.toFixed(2)} kg</td>
<td className="border border-border p-2 text-xs text-right text-card-foreground">{peca.peso_total.toFixed(2)} kg</td>
{/* Corte com check e data */}
<td className="border border-border p-2 text-xs text-center text-card-foreground">
{peca.processos.corte ? '✓' : ''}
{peca.processos.corte ? (
<div className="flex flex-col items-center justify-center leading-tight">
<span className="text-emerald-600 dark:text-emerald-400 font-bold text-sm">✓</span>
{peca.datasProcessos?.corte && (
<span className="text-[10px] text-muted-foreground font-medium">
{peca.datasProcessos.corte}
</span>
)}
</div>
) : ''}
</td>
{/* Solda com check e data */}
<td className="border border-border p-2 text-xs text-center text-card-foreground">
{!peca.tem_componentes ? 'S/M' : (peca.processos.solda ? '✓' : '')}
{!peca.tem_componentes ? (
<span className="text-purple-600 dark:text-purple-400 font-semibold">S/M</span>
) : peca.processos.solda ? (
<div className="flex flex-col items-center justify-center leading-tight">
<span className="text-emerald-600 dark:text-emerald-400 font-bold text-sm">✓</span>
{peca.datasProcessos?.solda && (
<span className="text-[10px] text-muted-foreground font-medium">
{peca.datasProcessos.solda}
</span>
)}
</div>
) : ''}
</td>
{/* Pintura com check e data */}
<td className="border border-border p-2 text-xs text-center text-card-foreground">
{peca.processos.pintura ? '✓' : ''}
{peca.processos.pintura ? (
<div className="flex flex-col items-center justify-center leading-tight">
<span className="text-emerald-600 dark:text-emerald-400 font-bold text-sm">✓</span>
{peca.datasProcessos?.pintura && (
<span className="text-[10px] text-muted-foreground font-medium">
{peca.datasProcessos.pintura}
</span>
)}
</div>
) : ''}
</td>
{/* Expedição com check e data */}
<td className="border border-border p-2 text-xs text-center text-card-foreground">
{peca.processos.expedicao ? '✓' : ''}
{peca.processos.expedicao ? (
<div className="flex flex-col items-center justify-center leading-tight">
<span className="text-emerald-600 dark:text-emerald-400 font-bold text-sm">✓</span>
{peca.datasProcessos?.expedicao && (
<span className="text-[10px] text-muted-foreground font-medium">
{peca.datasProcessos.expedicao}
</span>
)}
</div>
) : ''}
</td>
</tr>
))}
@@ -16,6 +16,12 @@ interface RelatorioPecasProcessoPDFProps {
pesoTotalPintura: number;
pesoTotalExpedicao: number;
};
percentuais?: {
corte: number;
solda: number;
pintura: number;
expedicao: number;
};
selectedOF: string;
selectedFase: string;
}
@@ -23,6 +29,7 @@ interface RelatorioPecasProcessoPDFProps {
export const RelatorioPecasProcessoPDF: React.FC<RelatorioPecasProcessoPDFProps> = ({
pecasComStatus,
estatisticas,
percentuais,
selectedOF,
selectedFase
}) => {
@@ -47,38 +54,53 @@ export const RelatorioPecasProcessoPDF: React.FC<RelatorioPecasProcessoPDFProps>
doc.setFont('helvetica', 'normal');
doc.text(`OF: ${selectedOF}${faseText} | Gerado em: ${new Date().toLocaleString('pt-BR')}`, 14, 23);
// Resumo por Processo em linha mais compacta
let yPos = 32;
doc.setFontSize(9);
// Resumo por Processo em box estilizado e alinhado
let yPos = 29;
doc.setFillColor(248, 250, 252);
doc.roundedRect(14, yPos, 182, 10, 1, 1, 'F');
doc.setDrawColor(226, 232, 240);
doc.setLineWidth(0.3);
doc.roundedRect(14, yPos, 182, 10, 1, 1, 'S');
doc.setFontSize(7.5);
doc.setFont('helvetica', 'bold');
doc.text(`Total Peças:`, 14, yPos);
doc.setFont('helvetica', 'normal');
doc.text(`${estatisticas.totalPecas}`, 36, yPos);
doc.setTextColor(71, 85, 105);
doc.text('Total Peças:', 17, yPos + 6.5);
doc.setTextColor(15, 23, 42);
doc.text(`${estatisticas.totalPecas}`, 33, yPos + 6.5);
doc.setFont('helvetica', 'bold');
doc.text(`Corte:`, 50, yPos);
doc.setFont('helvetica', 'normal');
doc.text(`${estatisticas.pesoTotalCorte.toFixed(0)} kg`, 62, yPos);
doc.setTextColor(71, 85, 105);
doc.text('Corte:', 44, yPos + 6.5);
doc.setTextColor(15, 43, 92);
doc.text(`${estatisticas.pesoTotalCorte.toFixed(0)} kg`, 54, yPos + 6.5);
doc.setTextColor(37, 99, 235);
doc.text(`(${(percentuais?.corte ?? 0).toFixed(1)}%)`, 70, yPos + 6.5);
doc.setFont('helvetica', 'bold');
doc.text(`Solda:`, 90, yPos);
doc.setFont('helvetica', 'normal');
doc.text(`${estatisticas.pesoTotalSolda.toFixed(0)} kg`, 102, yPos);
doc.setTextColor(71, 85, 105);
doc.text('Solda:', 86, yPos + 6.5);
doc.setTextColor(15, 43, 92);
doc.text(`${estatisticas.pesoTotalSolda.toFixed(0)} kg`, 96, yPos + 6.5);
doc.setTextColor(37, 99, 235);
doc.text(`(${(percentuais?.solda ?? 0).toFixed(1)}%)`, 112, yPos + 6.5);
doc.setFont('helvetica', 'bold');
doc.text(`Pintura:`, 130, yPos);
doc.setFont('helvetica', 'normal');
doc.text(`${estatisticas.pesoTotalPintura.toFixed(0)} kg`, 145, yPos);
doc.setTextColor(71, 85, 105);
doc.text('Pintura:', 127, yPos + 6.5);
doc.setTextColor(15, 43, 92);
doc.text(`${estatisticas.pesoTotalPintura.toFixed(0)} kg`, 138, yPos + 6.5);
doc.setTextColor(37, 99, 235);
doc.text(`(${(percentuais?.pintura ?? 0).toFixed(1)}%)`, 150, yPos + 6.5);
doc.setFont('helvetica', 'bold');
doc.text(`Expedição:`, 175, yPos);
doc.setFont('helvetica', 'normal');
doc.text(`${estatisticas.pesoTotalExpedicao.toFixed(0)} kg`, 192, yPos);
doc.setTextColor(71, 85, 105);
doc.text('Exp.:', 165, yPos + 6.5);
doc.setTextColor(15, 43, 92);
doc.text(`${estatisticas.pesoTotalExpedicao.toFixed(0)} kg`, 173, yPos + 6.5);
doc.setTextColor(37, 99, 235);
doc.text(`(${(percentuais?.expedicao ?? 0).toFixed(1)}%)`, 185, yPos + 6.5);
yPos = 38; // Ajusta yPos para o início da tabela
yPos = 42; // Ajusta yPos para o início da tabela
// Preparar dados para a tabela
// Preparar dados para a tabela com indicação de data abaixo do check
const tableData = pecasComStatus.map(peca => [
peca.of_number,
peca.etapa_fase,
@@ -86,10 +108,10 @@ export const RelatorioPecasProcessoPDF: React.FC<RelatorioPecasProcessoPDFProps>
peca.quantidade.toString(),
`${peca.peso_unitario.toFixed(2)} kg`,
`${peca.peso_total.toFixed(2)} kg`,
peca.processos.corte ? 'OK' : '',
!peca.tem_componentes ? 'S/M' : (peca.processos.solda ? 'OK' : ''),
peca.processos.pintura ? 'OK' : '',
peca.processos.expedicao ? 'OK' : ''
peca.processos.corte ? (peca.datasProcessos?.corte ? `✓\n${peca.datasProcessos.corte}` : '✓') : '',
!peca.tem_componentes ? 'S/M' : (peca.processos.solda ? (peca.datasProcessos?.solda ? `✓\n${peca.datasProcessos.solda}` : '✓') : ''),
peca.processos.pintura ? (peca.datasProcessos?.pintura ? `✓\n${peca.datasProcessos.pintura}` : '✓') : '',
peca.processos.expedicao ? (peca.datasProcessos?.expedicao ? `✓\n${peca.datasProcessos.expedicao}` : '✓') : ''
]);
// Cabeçalhos da tabela
@@ -14,6 +14,12 @@ interface RelatorioPecasProcessoPrintProps {
pesoTotalPintura: number;
pesoTotalExpedicao: number;
};
percentuais?: {
corte: number;
solda: number;
pintura: number;
expedicao: number;
};
selectedOF: string;
selectedFase: string;
}
@@ -21,6 +27,7 @@ interface RelatorioPecasProcessoPrintProps {
export const RelatorioPecasProcessoPrint: React.FC<RelatorioPecasProcessoPrintProps> = ({
pecasComStatus,
estatisticas,
percentuais,
selectedOF,
selectedFase
}) => {
@@ -128,10 +135,10 @@ export const RelatorioPecasProcessoPrint: React.FC<RelatorioPecasProcessoPrintPr
<section style="margin-bottom: 12px;">
<div style="display: flex; flex-wrap: wrap; justify-content: space-between; font-size: 11px; color: #4b5563; padding: 6px 12px; border: 1px solid #e5e7eb; border-radius: 6px; background-color: #f9fafb;" class="summary-info">
<div><strong>Total Peças:</strong> ${estatisticas.totalPecas}</div>
<div><strong>Corte:</strong> ${estatisticas.pesoTotalCorte.toFixed(0)} kg</div>
<div><strong>Solda:</strong> ${estatisticas.pesoTotalSolda.toFixed(0)} kg</div>
<div><strong>Pintura:</strong> ${estatisticas.pesoTotalPintura.toFixed(0)} kg</div>
<div><strong>Expedição:</strong> ${estatisticas.pesoTotalExpedicao.toFixed(0)} kg</div>
<div><strong>Corte:</strong> ${estatisticas.pesoTotalCorte.toFixed(0)} kg <span style="color: #2563eb; font-weight: bold;">(${(percentuais?.corte ?? 0).toFixed(1)}%)</span></div>
<div><strong>Solda:</strong> ${estatisticas.pesoTotalSolda.toFixed(0)} kg <span style="color: #2563eb; font-weight: bold;">(${(percentuais?.solda ?? 0).toFixed(1)}%)</span></div>
<div><strong>Pintura:</strong> ${estatisticas.pesoTotalPintura.toFixed(0)} kg <span style="color: #2563eb; font-weight: bold;">(${(percentuais?.pintura ?? 0).toFixed(1)}%)</span></div>
<div><strong>Expedição:</strong> ${estatisticas.pesoTotalExpedicao.toFixed(0)} kg <span style="color: #2563eb; font-weight: bold;">(${(percentuais?.expedicao ?? 0).toFixed(1)}%)</span></div>
</div>
</section>
@@ -157,14 +164,34 @@ export const RelatorioPecasProcessoPrint: React.FC<RelatorioPecasProcessoPrintPr
<tr>
<td>${peca.of_number}</td>
<td>${peca.etapa_fase}</td>
<td>${peca.marca}</td>
<td style="font-weight: 600;">${peca.marca}</td>
<td>${peca.quantidade}</td>
<td class="text-right">${peca.peso_unitario.toFixed(2)} kg</td>
<td class="text-right">${peca.peso_total.toFixed(2)} kg</td>
<td>${peca.processos.corte ? 'OK' : ''}</td>
<td>${!peca.tem_componentes ? 'S/M' : (peca.processos.solda ? 'OK' : '')}</td>
<td>${peca.processos.pintura ? 'OK' : ''}</td>
<td>${peca.processos.expedicao ? 'OK' : ''}</td>
<td>
${peca.processos.corte ? `
<div style="font-weight: bold; color: #16a34a; font-size: 9pt; line-height: 1;">✓</div>
${peca.datasProcessos?.corte ? `<div style="font-size: 6.5pt; color: #6b7280; margin-top: 1px;">${peca.datasProcessos.corte}</div>` : ''}
` : ''}
</td>
<td>
${!peca.tem_componentes ? '<span style="color: #9333ea; font-weight: 600;">S/M</span>' : (peca.processos.solda ? `
<div style="font-weight: bold; color: #16a34a; font-size: 9pt; line-height: 1;">✓</div>
${peca.datasProcessos?.solda ? `<div style="font-size: 6.5pt; color: #6b7280; margin-top: 1px;">${peca.datasProcessos.solda}</div>` : ''}
` : '')}
</td>
<td>
${peca.processos.pintura ? `
<div style="font-weight: bold; color: #16a34a; font-size: 9pt; line-height: 1;">✓</div>
${peca.datasProcessos?.pintura ? `<div style="font-size: 6.5pt; color: #6b7280; margin-top: 1px;">${peca.datasProcessos.pintura}</div>` : ''}
` : ''}
</td>
<td>
${peca.processos.expedicao ? `
<div style="font-weight: bold; color: #16a34a; font-size: 9pt; line-height: 1;">✓</div>
${peca.datasProcessos?.expedicao ? `<div style="font-size: 6.5pt; color: #6b7280; margin-top: 1px;">${peca.datasProcessos.expedicao}</div>` : ''}
` : ''}
</td>
</tr>
`).join('')}
</tbody>
+118 -19
View File
@@ -18,6 +18,12 @@ export interface PecaComStatus {
pintura: boolean;
expedicao: boolean;
};
datasProcessos?: {
corte?: string | null;
solda?: string | null;
pintura?: string | null;
expedicao?: string | null;
};
}
export interface ResumoProcesso {
@@ -26,6 +32,29 @@ export interface ResumoProcesso {
quantidadePecas: number;
}
// Formata data ISO ou YYYY-MM-DD para 'dd/mm'
export const formatarDiaMes = (dataStr?: string | null): string => {
if (!dataStr) return '';
try {
const raw = dataStr.split('T')[0];
const partes = raw.split('-');
if (partes.length === 3) {
const dia = partes[2].padStart(2, '0');
const mes = partes[1].padStart(2, '0');
return `${dia}/${mes}`;
}
const d = new Date(dataStr);
if (!isNaN(d.getTime())) {
const dia = d.getDate().toString().padStart(2, '0');
const mes = (d.getMonth() + 1).toString().padStart(2, '0');
return `${dia}/${mes}`;
}
} catch (e) {
// fallback
}
return '';
};
// Função para ordenação numérica natural
const naturalSort = (a: string, b: string): number => {
const collator = new Intl.Collator(undefined, {
@@ -86,39 +115,103 @@ export const useRelatorioPecasProcesso = (ofNumber: string) => {
const processosMap = new Map(processosData?.map(p => [p.nome, p.id]) || []);
console.log('Processos mapeados:', Object.fromEntries(processosMap));
// Buscar apontamentos para todas as peças da OF
// Buscar apontamentos para todas as peças da OF incluindo data_apontamento e created_at
const pecaIds = pecasData.map(p => p.id);
const { data: apontamentosData, error: apontamentosError } = await supabase
.from('apontamentos_producao')
.select(`
peca_id,
processo_id,
quantidade_produzida,
processos_fabricacao!apontamentos_producao_processo_id_fkey(nome)
`)
.eq('of_number', ofNumber)
.in('peca_id', pecaIds);
const [resApontamentos, resRomaneios] = await Promise.all([
supabase
.from('apontamentos_producao')
.select(`
peca_id,
processo_id,
quantidade_produzida,
data_apontamento,
created_at,
processos_fabricacao!apontamentos_producao_processo_id_fkey(nome)
`)
.eq('of_number', ofNumber)
.in('peca_id', pecaIds),
if (apontamentosError) {
console.error('Erro ao buscar apontamentos:', apontamentosError);
throw apontamentosError;
// Buscar romaneios de expedição para garantir datas e status de expedição
supabase
.from('itens_romaneio_pecas')
.select(`
marca,
peca_id,
quantidade_expedida,
created_at,
romaneios_expedicao!inner(of_number, data_saida, data_emissao, created_at)
`)
.eq('romaneios_expedicao.of_number', ofNumber)
]);
if (resApontamentos.error) {
console.error('Erro ao buscar apontamentos:', resApontamentos.error);
throw resApontamentos.error;
}
console.log('Apontamentos encontrados:', apontamentosData?.length || 0);
const apontamentosData = resApontamentos.data || [];
const romaneiosData = resRomaneios.data || [];
// Mapear status dos processos por peça
console.log('Apontamentos encontrados:', apontamentosData.length);
// Mapear status dos processos por peça e guardar a ÚLTIMA data apontada de cada processo
const statusPorPeca = new Map<string, Set<string>>();
const datasPorPeca = new Map<string, { corte: string; solda: string; pintura: string; expedicao: string }>();
apontamentosData?.forEach(apt => {
apontamentosData.forEach(apt => {
if (!statusPorPeca.has(apt.peca_id)) {
statusPorPeca.set(apt.peca_id, new Set());
}
statusPorPeca.get(apt.peca_id)!.add(apt.processos_fabricacao.nome);
const nomeProc = apt.processos_fabricacao?.nome || '';
statusPorPeca.get(apt.peca_id)!.add(nomeProc);
if (!datasPorPeca.has(apt.peca_id)) {
datasPorPeca.set(apt.peca_id, { corte: '', solda: '', pintura: '', expedicao: '' });
}
const datas = datasPorPeca.get(apt.peca_id)!;
const dataApt = apt.data_apontamento || apt.created_at || '';
const nomeLower = nomeProc.toLowerCase();
if (dataApt) {
if (nomeLower.includes('corte')) {
if (!datas.corte || dataApt > datas.corte) datas.corte = dataApt;
} else if (nomeLower.includes('solda')) {
if (!datas.solda || dataApt > datas.solda) datas.solda = dataApt;
} else if (nomeLower.includes('pint') || nomeLower.includes('galv')) {
if (!datas.pintura || dataApt > datas.pintura) datas.pintura = dataApt;
} else if (nomeLower.includes('exped')) {
if (!datas.expedicao || dataApt > datas.expedicao) datas.expedicao = dataApt;
}
}
});
// Construir array de peças com status
// Adicionar informações vindas dos Romaneios de Expedição
romaneiosData.forEach((item: any) => {
const pecaAlvo = pecasData.find(p => p.id === item.peca_id || p.marca === item.marca);
if (pecaAlvo) {
if (!statusPorPeca.has(pecaAlvo.id)) {
statusPorPeca.set(pecaAlvo.id, new Set());
}
statusPorPeca.get(pecaAlvo.id)!.add('Expedicao');
if (!datasPorPeca.has(pecaAlvo.id)) {
datasPorPeca.set(pecaAlvo.id, { corte: '', solda: '', pintura: '', expedicao: '' });
}
const datas = datasPorPeca.get(pecaAlvo.id)!;
const dataExp = item.romaneios_expedicao?.data_saida ||
item.romaneios_expedicao?.data_emissao ||
item.romaneios_expedicao?.created_at ||
item.created_at || '';
if (dataExp && (!datas.expedicao || dataExp > datas.expedicao)) {
datas.expedicao = dataExp;
}
}
});
// Construir array de peças com status e última data apontada
const pecasComStatusFormatadas: PecaComStatus[] = pecasData.map(peca => {
const processosRealizados = statusPorPeca.get(peca.id) || new Set();
const datas = datasPorPeca.get(peca.id) || { corte: '', solda: '', pintura: '', expedicao: '' };
return {
id: peca.id,
@@ -136,6 +229,12 @@ export const useRelatorioPecasProcesso = (ofNumber: string) => {
processosRealizados.has('Pintura/Galv') ||
processosRealizados.has('Pintura'),
expedicao: processosRealizados.has('Expedicao')
},
datasProcessos: {
corte: formatarDiaMes(datas.corte),
solda: formatarDiaMes(datas.solda),
pintura: formatarDiaMes(datas.pintura),
expedicao: formatarDiaMes(datas.expedicao)
}
};
});