fix: isolar componentes e aplicar trava de teto na disponibilidade do Modo Smart
This commit is contained in:
@@ -1,2 +0,0 @@
|
|||||||
// Script temporário de auditoria da OF B134
|
|
||||||
export {};
|
|
||||||
@@ -110,11 +110,11 @@ export default function Visualizador3D() {
|
|||||||
.select('id, of_number, etapa_fase, marca, descricao, quantidade, peso_unitario, peso_total, perfil_principal, material')
|
.select('id, of_number, etapa_fase, marca, descricao, quantidade, peso_unitario, peso_total, perfil_principal, material')
|
||||||
.eq('of_number', selectedOF);
|
.eq('of_number', selectedOF);
|
||||||
|
|
||||||
// Fetch apontamentos com join de peca e processo
|
// Fetch apontamentos com join de peca e processo (apenas peças mestres)
|
||||||
const { data: apontamentosData, error: errorApontamentos } = await supabase
|
const { data: apontamentosData, error: errorApontamentos } = await supabase
|
||||||
.from('apontamentos_producao' as any)
|
.from('apontamentos_producao' as any)
|
||||||
.select(`
|
.select(`
|
||||||
id, of_number, peca_id, quantidade_produzida,
|
id, of_number, peca_id, quantidade_produzida, tipo_apontamento, componente_id,
|
||||||
peca:pecas!apontamentos_producao_peca_id_fkey(marca, etapa_fase),
|
peca:pecas!apontamentos_producao_peca_id_fkey(marca, etapa_fase),
|
||||||
processo:processos_fabricacao!apontamentos_producao_processo_id_fkey(nome, cor, ordem)
|
processo:processos_fabricacao!apontamentos_producao_processo_id_fkey(nome, cor, ordem)
|
||||||
`)
|
`)
|
||||||
@@ -188,6 +188,10 @@ export default function Visualizador3D() {
|
|||||||
apontamentosData.sort((a: any, b: any) => (a.processo?.ordem || 0) - (b.processo?.ordem || 0));
|
apontamentosData.sort((a: any, b: any) => (a.processo?.ordem || 0) - (b.processo?.ordem || 0));
|
||||||
|
|
||||||
apontamentosData.forEach((ap: any) => {
|
apontamentosData.forEach((ap: any) => {
|
||||||
|
// Ignora apontamentos de componentes para não inflar as peças mestres
|
||||||
|
if (ap.tipo_apontamento && ap.tipo_apontamento !== 'peca') return;
|
||||||
|
if (ap.componente_id) return;
|
||||||
|
|
||||||
const marca = ap.peca?.marca ? String(ap.peca.marca).trim() : '';
|
const marca = ap.peca?.marca ? String(ap.peca.marca).trim() : '';
|
||||||
const fase = ap.peca?.etapa_fase ? String(ap.peca.etapa_fase).trim() : '';
|
const fase = ap.peca?.etapa_fase ? String(ap.peca.etapa_fase).trim() : '';
|
||||||
if (marca) {
|
if (marca) {
|
||||||
|
|||||||
@@ -90,10 +90,10 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
|
|||||||
.from('processos_fabricacao')
|
.from('processos_fabricacao')
|
||||||
.select('id, nome, ordem'),
|
.select('id, nome, ordem'),
|
||||||
|
|
||||||
// 3. Apontamentos da OF
|
// 3. Apontamentos da OF (apenas peças mestres)
|
||||||
supabase
|
supabase
|
||||||
.from('apontamentos_producao')
|
.from('apontamentos_producao')
|
||||||
.select('peca_id, processo_id, quantidade_produzida')
|
.select('peca_id, processo_id, quantidade_produzida, tipo_apontamento, componente_id')
|
||||||
.eq('of_number', obra.of_number),
|
.eq('of_number', obra.of_number),
|
||||||
|
|
||||||
// 4. Expedição em Romaneios (APENAS ROMANEIOS ENTREGUES E MAPEANDO POR PECA_ID PARA EVITAR CONFLITO DE FASE)
|
// 4. Expedição em Romaneios (APENAS ROMANEIOS ENTREGUES E MAPEANDO POR PECA_ID PARA EVITAR CONFLITO DE FASE)
|
||||||
@@ -132,6 +132,10 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
|
|||||||
>();
|
>();
|
||||||
|
|
||||||
(resApontamentos.data || []).forEach((ap: any) => {
|
(resApontamentos.data || []).forEach((ap: any) => {
|
||||||
|
// Ignora apontamentos de componentes para não inflar as quantidades da peça mestre
|
||||||
|
if (ap.tipo_apontamento && ap.tipo_apontamento !== 'peca') return;
|
||||||
|
if (ap.componente_id) return;
|
||||||
|
|
||||||
const pecaId = ap.peca_id;
|
const pecaId = ap.peca_id;
|
||||||
const nomeProc = mapaNomeProcesso.get(ap.processo_id) || '';
|
const nomeProc = mapaNomeProcesso.get(ap.processo_id) || '';
|
||||||
const qtd = Number(ap.quantidade_produzida || 0);
|
const qtd = Number(ap.quantidade_produzida || 0);
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ export const calcularSaldoProcessoPeca = (
|
|||||||
if (procAnteriorValido) {
|
if (procAnteriorValido) {
|
||||||
const keyAnt = `${peca.id}_${procAnteriorValido.id}`;
|
const keyAnt = `${peca.id}_${procAnteriorValido.id}`;
|
||||||
const qtdApontadaAnterior = mapaProd.get(keyAnt) || 0;
|
const qtdApontadaAnterior = mapaProd.get(keyAnt) || 0;
|
||||||
qtdDisponivelParaEntrar = qtdApontadaAnterior;
|
// Trava de teto: o saldo para entrar jamais pode exceder o total da peça
|
||||||
|
qtdDisponivelParaEntrar = Math.min(Number(peca.quantidade) || 0, qtdApontadaAnterior);
|
||||||
|
|
||||||
if (qtdApontadaAnterior === 0) {
|
if (qtdApontadaAnterior === 0) {
|
||||||
motivoBloqueio = `Aguardando ${procAnteriorValido.nome}`;
|
motivoBloqueio = `Aguardando ${procAnteriorValido.nome}`;
|
||||||
@@ -127,7 +128,7 @@ export const calcularSaldoProcessoPeca = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const saldo = Math.max(0, qtdDisponivelParaEntrar - jaProduzidoAtual);
|
const saldo = Math.max(0, Math.min(Number(peca.quantidade) || 0, qtdDisponivelParaEntrar) - jaProduzidoAtual);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
saldo,
|
saldo,
|
||||||
@@ -149,6 +150,8 @@ interface ApontamentoItem {
|
|||||||
status_confirmacao?: string;
|
status_confirmacao?: string;
|
||||||
forcado_por_user_nome?: string;
|
forcado_por_user_nome?: string;
|
||||||
usuario_nome?: string;
|
usuario_nome?: string;
|
||||||
|
tipo_apontamento?: string;
|
||||||
|
componente_id?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
|
export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
|
||||||
@@ -190,7 +193,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
|
|||||||
.eq('of_number', obra.of_number),
|
.eq('of_number', obra.of_number),
|
||||||
supabase
|
supabase
|
||||||
.from('apontamentos_producao')
|
.from('apontamentos_producao')
|
||||||
.select('id, peca_id, processo_id, quantidade_produzida, is_forcado, status_confirmacao, forcado_por_user_nome, usuario_nome')
|
.select('id, peca_id, processo_id, quantidade_produzida, is_forcado, status_confirmacao, forcado_por_user_nome, usuario_nome, tipo_apontamento, componente_id')
|
||||||
.eq('of_number', obra.of_number),
|
.eq('of_number', obra.of_number),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -224,10 +227,14 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
|
|||||||
return lista.length > 0 ? lista : ['Geral'];
|
return lista.length > 0 ? lista : ['Geral'];
|
||||||
}, [pecas]);
|
}, [pecas]);
|
||||||
|
|
||||||
// Mapa de produção acumulada por peca_id e processo_id
|
// Mapa de produção acumulada por peca_id e processo_id (apenas apontamentos de peças mestres)
|
||||||
const mapaProducao = useMemo(() => {
|
const mapaProducao = useMemo(() => {
|
||||||
const mapa = new Map<string, number>();
|
const mapa = new Map<string, number>();
|
||||||
apontamentosExistentes.forEach((ap) => {
|
apontamentosExistentes.forEach((ap) => {
|
||||||
|
// Ignora apontamentos de componentes para não inflar a contagem da peça pai
|
||||||
|
if (ap.tipo_apontamento && ap.tipo_apontamento !== 'peca') return;
|
||||||
|
if (ap.componente_id) return;
|
||||||
|
|
||||||
const key = `${ap.peca_id}_${ap.processo_id}`;
|
const key = `${ap.peca_id}_${ap.processo_id}`;
|
||||||
const atual = mapa.get(key) || 0;
|
const atual = mapa.get(key) || 0;
|
||||||
mapa.set(key, atual + Number(ap.quantidade_produzida || 0));
|
mapa.set(key, atual + Number(ap.quantidade_produzida || 0));
|
||||||
@@ -238,7 +245,11 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
|
|||||||
// Apontamentos forçados que ainda estão pendentes de confirmação de baixa
|
// Apontamentos forçados que ainda estão pendentes de confirmação de baixa
|
||||||
const apontamentosPendentes = useMemo(() => {
|
const apontamentosPendentes = useMemo(() => {
|
||||||
return apontamentosExistentes.filter(
|
return apontamentosExistentes.filter(
|
||||||
(ap) => ap.is_forcado && ap.status_confirmacao === 'pendente_confirmacao'
|
(ap) =>
|
||||||
|
(!ap.tipo_apontamento || ap.tipo_apontamento === 'peca') &&
|
||||||
|
!ap.componente_id &&
|
||||||
|
ap.is_forcado &&
|
||||||
|
ap.status_confirmacao === 'pendente_confirmacao'
|
||||||
);
|
);
|
||||||
}, [apontamentosExistentes]);
|
}, [apontamentosExistentes]);
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export const SmartViewer3DFlow: React.FC<SmartViewer3DFlowProps> = ({
|
|||||||
supabase
|
supabase
|
||||||
.from('apontamentos_producao' as any)
|
.from('apontamentos_producao' as any)
|
||||||
.select(`
|
.select(`
|
||||||
id, of_number, peca_id, quantidade_produzida,
|
id, of_number, peca_id, quantidade_produzida, tipo_apontamento, componente_id,
|
||||||
peca:pecas!apontamentos_producao_peca_id_fkey(marca, etapa_fase),
|
peca:pecas!apontamentos_producao_peca_id_fkey(marca, etapa_fase),
|
||||||
processo:processos_fabricacao!apontamentos_producao_processo_id_fkey(nome, cor, ordem)
|
processo:processos_fabricacao!apontamentos_producao_processo_id_fkey(nome, cor, ordem)
|
||||||
`)
|
`)
|
||||||
@@ -139,6 +139,10 @@ export const SmartViewer3DFlow: React.FC<SmartViewer3DFlowProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
sortedApontamentos.forEach((ap: any) => {
|
sortedApontamentos.forEach((ap: any) => {
|
||||||
|
// Ignora apontamentos de componentes para não inflar as peças mestres
|
||||||
|
if (ap.tipo_apontamento && ap.tipo_apontamento !== 'peca') return;
|
||||||
|
if (ap.componente_id) return;
|
||||||
|
|
||||||
const marca = ap.peca?.marca ? String(ap.peca.marca).trim() : '';
|
const marca = ap.peca?.marca ? String(ap.peca.marca).trim() : '';
|
||||||
const fase = ap.peca?.etapa_fase ? String(ap.peca.etapa_fase).trim() : '';
|
const fase = ap.peca?.etapa_fase ? String(ap.peca.etapa_fase).trim() : '';
|
||||||
if (marca) {
|
if (marca) {
|
||||||
|
|||||||
Reference in New Issue
Block a user