feat: add direct db injection button to Bocad Converter
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
|||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import * as XLSX from 'xlsx';
|
import * as XLSX from 'xlsx';
|
||||||
|
import { usePecas } from '@/hooks/usePecas';
|
||||||
|
|
||||||
export interface BocadConvertedPiece {
|
export interface BocadConvertedPiece {
|
||||||
of: string;
|
of: string;
|
||||||
@@ -39,6 +40,7 @@ export interface BocadConvertedPiece {
|
|||||||
perfilPrincipal: string;
|
perfilPrincipal: string;
|
||||||
comprimentoRef: number | string;
|
comprimentoRef: number | string;
|
||||||
qtdComponentesFilhos: number;
|
qtdComponentesFilhos: number;
|
||||||
|
components?: RawBocadComponent[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RawBocadComponent {
|
interface RawBocadComponent {
|
||||||
@@ -66,8 +68,10 @@ interface RawBocadAssembly {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const BocadConverter: React.FC = () => {
|
export const BocadConverter: React.FC = () => {
|
||||||
|
const { importPecas } = usePecas();
|
||||||
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
||||||
const [isProcessing, setIsProcessing] = useState(false);
|
const [isProcessing, setIsProcessing] = useState(false);
|
||||||
|
const [isDirectImporting, setIsDirectImporting] = useState(false);
|
||||||
const [tratamentoGlobal, setTratamentoGlobal] = useState<'pintura' | 'galvanizacao'>('pintura');
|
const [tratamentoGlobal, setTratamentoGlobal] = useState<'pintura' | 'galvanizacao'>('pintura');
|
||||||
const [extractedPieces, setExtractedPieces] = useState<BocadConvertedPiece[]>([]);
|
const [extractedPieces, setExtractedPieces] = useState<BocadConvertedPiece[]>([]);
|
||||||
const [headerOf, setHeaderOf] = useState<string>('');
|
const [headerOf, setHeaderOf] = useState<string>('');
|
||||||
@@ -410,7 +414,8 @@ export const BocadConverter: React.FC = () => {
|
|||||||
material: normalizedMat,
|
material: normalizedMat,
|
||||||
perfilPrincipal: perfilPrincipal,
|
perfilPrincipal: perfilPrincipal,
|
||||||
comprimentoRef: compRef,
|
comprimentoRef: compRef,
|
||||||
qtdComponentesFilhos: whiteRowsCount
|
qtdComponentesFilhos: whiteRowsCount,
|
||||||
|
components: asm.components
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -515,6 +520,66 @@ export const BocadConverter: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDirectImport = async () => {
|
||||||
|
if (extractedPieces.length === 0) return;
|
||||||
|
setIsDirectImporting(true);
|
||||||
|
try {
|
||||||
|
const importacaoRows: any[] = [];
|
||||||
|
extractedPieces.forEach((item) => {
|
||||||
|
if (item.compostoPorComponentes === 'SIM' && item.components && item.components.length > 0) {
|
||||||
|
item.components.forEach((comp) => {
|
||||||
|
importacaoRows.push({
|
||||||
|
of_number: item.of,
|
||||||
|
etapa_fase: item.fase,
|
||||||
|
marca: item.marca,
|
||||||
|
descricao: item.descricao,
|
||||||
|
quantidade: Number(item.quantidade),
|
||||||
|
peso_unitario: item.pesoUnitario || 0,
|
||||||
|
peso_total: item.pesoTotal || 0,
|
||||||
|
tratamento_superficial: item.tratamentoSuperficial,
|
||||||
|
material: item.material,
|
||||||
|
perfil_principal: item.perfilPrincipal,
|
||||||
|
tem_componentes: true,
|
||||||
|
marca_componente: comp.marca || '',
|
||||||
|
descricao_componente: comp.perfil || item.descricao,
|
||||||
|
perfil_componente: comp.perfil || item.descricao,
|
||||||
|
peso_unitario_componente: comp.pesoUnit || 0,
|
||||||
|
quantidade_por_peca: Number(comp.quant) || 1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
importacaoRows.push({
|
||||||
|
of_number: item.of,
|
||||||
|
etapa_fase: item.fase,
|
||||||
|
marca: item.marca,
|
||||||
|
descricao: item.descricao,
|
||||||
|
quantidade: Number(item.quantidade),
|
||||||
|
peso_unitario: item.pesoUnitario || 0,
|
||||||
|
peso_total: item.pesoTotal || 0,
|
||||||
|
tratamento_superficial: item.tratamentoSuperficial,
|
||||||
|
material: item.material,
|
||||||
|
perfil_principal: item.perfilPrincipal,
|
||||||
|
tem_componentes: false,
|
||||||
|
marca_componente: '',
|
||||||
|
descricao_componente: '',
|
||||||
|
perfil_componente: '',
|
||||||
|
peso_unitario_componente: 0,
|
||||||
|
quantidade_por_peca: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await importPecas(importacaoRows);
|
||||||
|
toast.success(`${extractedPieces.length} peças foram importadas com sucesso!`);
|
||||||
|
addLog(`✅ Importação concluída: ${extractedPieces.length} peças gravadas no banco.`);
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('Erro na importação direta:', err);
|
||||||
|
toast.error(`Falha ao importar: ${err?.message || 'Erro no banco'}`);
|
||||||
|
} finally {
|
||||||
|
setIsDirectImporting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const totalPesoGeral = extractedPieces.reduce((acc, curr) => acc + (curr.pesoTotal || 0), 0);
|
const totalPesoGeral = extractedPieces.reduce((acc, curr) => acc + (curr.pesoTotal || 0), 0);
|
||||||
const totalPecasCompostas = extractedPieces.filter((p) => p.compostoPorComponentes === 'SIM').length;
|
const totalPecasCompostas = extractedPieces.filter((p) => p.compostoPorComponentes === 'SIM').length;
|
||||||
const totalPecasSimples = extractedPieces.filter((p) => p.compostoPorComponentes === 'NAO').length;
|
const totalPecasSimples = extractedPieces.filter((p) => p.compostoPorComponentes === 'NAO').length;
|
||||||
@@ -689,11 +754,30 @@ export const BocadConverter: React.FC = () => {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
onClick={exportToOfficialExcel}
|
onClick={exportToOfficialExcel}
|
||||||
className="bg-emerald-600 hover:bg-emerald-500 text-white font-semibold text-xs px-4 h-9 shadow-lg shadow-emerald-950/40"
|
variant="outline"
|
||||||
|
className="border-emerald-600/60 text-emerald-400 hover:bg-emerald-600/10 font-semibold text-xs px-3.5 h-9"
|
||||||
>
|
>
|
||||||
<Download className="w-4 h-4 mr-1.5" />
|
<Download className="w-4 h-4 mr-1.5" />
|
||||||
Baixar Planilha Padrão (.xlsx)
|
Baixar Planilha Padrão (.xlsx)
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={handleDirectImport}
|
||||||
|
disabled={isDirectImporting}
|
||||||
|
className="bg-indigo-600 hover:bg-indigo-500 text-white font-semibold text-xs px-4 h-9 shadow-lg shadow-indigo-950/40"
|
||||||
|
>
|
||||||
|
{isDirectImporting ? (
|
||||||
|
<>
|
||||||
|
<RefreshCw className="w-4 h-4 mr-1.5 animate-spin" />
|
||||||
|
Gravando no Banco...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Upload className="w-4 h-4 mr-1.5" />
|
||||||
|
cadastrar peças na OF
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user