se modifico pedimentoDetail
This commit is contained in:
1
.env
1
.env
@@ -2,3 +2,4 @@ VITE_DEBUG_MODE=true
|
||||
|
||||
VITE_EFC_API_URL=http://192.168.1.79:8000/api/v1
|
||||
VITE_EFC_MICROSERVICE_URL=http://192.168.1.79:8001/api/v1
|
||||
VITE_EFC_MICROSERVICE_URL_2=http://192.168.1.79:8001/api/v2
|
||||
|
||||
@@ -25,6 +25,7 @@ import { useNotification } from '../context/NotificationContext';
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
const MICROSERVICE_URL = import.meta.env.VITE_EFC_MICROSERVICE_URL;
|
||||
const MICROSERVICE_URL_2 = import.meta.env.VITE_EFC_MICROSERVICE_URL_2;
|
||||
|
||||
// Funciones auxiliares para estados y servicios (copiadas de procesos.js)
|
||||
const getEstadoLabel = (estado) => {
|
||||
@@ -196,6 +197,108 @@ export default function PedimentoDetail() {
|
||||
const [downloadingPartidas, setDownloadingPartidas] = useState(false);
|
||||
const [downloadingAllPartidas, setDownloadingAllPartidas] = useState(false);
|
||||
|
||||
// Estados para credenciales VUCEM
|
||||
const [credenciales, setCredenciales] = useState([]);
|
||||
const [processingPartida, setProcessingPartida] = useState(null);
|
||||
const [processingCove, setProcessingCove] = useState(null);
|
||||
const [processingAcuseCove, setProcessingAcuseCove] = useState(null);
|
||||
const [processingEdoc, setProcessingEdoc] = useState(null);
|
||||
const [processingAcuseEdoc, setProcessingAcuseEdoc] = useState(null);
|
||||
|
||||
// Función para obtener credenciales VUCEM
|
||||
const fetchCredenciales = async (contribuyente) => {
|
||||
try {
|
||||
const response = await fetchWithAuth(`${API_URL}/vucem/vucem/?importador=${contribuyente}`);
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
|
||||
// La API devuelve un array directamente, no un objeto con results
|
||||
const credenciales = Array.isArray(data) ? data : (data.results || []);
|
||||
|
||||
return credenciales;
|
||||
}
|
||||
return [];
|
||||
} catch (error) {
|
||||
console.error('Error fetching credenciales:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// Función para procesar partida
|
||||
const handlePartidaProcess = async (partida) => {
|
||||
setProcessingPartida(partida.id);
|
||||
|
||||
try {
|
||||
// Obtener credenciales para el contribuyente del pedimento
|
||||
const credencialesList = await fetchCredenciales(pedimento.contribuyente);
|
||||
|
||||
if (credencialesList.length === 0) {
|
||||
showMessage('No se encontraron credenciales VUCEM para este contribuyente', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Usar la primera credencial activa disponible
|
||||
const credencial = credencialesList.find(c => c.is_active) || credencialesList[0];
|
||||
|
||||
const requestBody = {
|
||||
partida: {
|
||||
id: partida.id,
|
||||
numero: partida.numero_partida
|
||||
},
|
||||
pedimento: {
|
||||
id: pedimento.id,
|
||||
pedimento: pedimento.pedimento,
|
||||
pedimento_app: pedimento.pedimento_app,
|
||||
aduana: pedimento.aduana,
|
||||
patente: pedimento.patente,
|
||||
organizacion: pedimento.organizacion,
|
||||
regimen: pedimento.regimen || "test",
|
||||
clave_pedimento: pedimento.clave_pedimento || "test",
|
||||
numero_operacion: pedimento.numero_operacion || ""
|
||||
},
|
||||
credencial: {
|
||||
id: credencial.id,
|
||||
user: credencial.usuario,
|
||||
password: credencial.password,
|
||||
efirma: credencial.efirma,
|
||||
// Convertir URLs completas a rutas relativas
|
||||
key: credencial.key ? credencial.key.split('/').slice(-2).join('/') : '',
|
||||
cer: credencial.cer ? credencial.cer.split('/').slice(-2).join('/') : '',
|
||||
is_active: credencial.is_active,
|
||||
organizacion: credencial.organizacion
|
||||
}
|
||||
};
|
||||
|
||||
// Verificar si MICROSERVICE_URL_2 está definido
|
||||
if (!MICROSERVICE_URL_2) {
|
||||
throw new Error('La variable de entorno VITE_EFC_MICROSERVICE_URL_2 no está configurada');
|
||||
}
|
||||
|
||||
const response = await fetchWithAuth(`${MICROSERVICE_URL_2}/services/partida/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
showMessage('Partida procesada correctamente', 'success');
|
||||
} else {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || 'Error al procesar la partida');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error procesando partida:', error);
|
||||
showMessage(`Error al procesar la partida: ${error.message}`, 'error');
|
||||
} finally {
|
||||
setProcessingPartida(null);
|
||||
}
|
||||
};
|
||||
|
||||
// Función para obtener partidas
|
||||
const fetchPedimentoPartidas = async (page = 1, pageSize = 10, filters = {}) => {
|
||||
console.log('fetchPedimentoPartidas called with:', { page, pageSize, filters });
|
||||
@@ -1201,6 +1304,300 @@ export default function PedimentoDetail() {
|
||||
// Aquí implementarías la lógica de petición específica para COVEs
|
||||
};
|
||||
|
||||
// Función para procesar COVE
|
||||
const handleCoveProcess = async (cove) => {
|
||||
setProcessingCove(cove.id);
|
||||
|
||||
try {
|
||||
// Obtener credenciales para el contribuyente del pedimento
|
||||
const credencialesList = await fetchCredenciales(pedimento.contribuyente);
|
||||
|
||||
if (credencialesList.length === 0) {
|
||||
showMessage('No se encontraron credenciales VUCEM para este contribuyente', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Usar la primera credencial activa disponible
|
||||
const credencial = credencialesList.find(c => c.is_active) || credencialesList[0];
|
||||
|
||||
const requestBody = {
|
||||
cove: {
|
||||
id: cove.id,
|
||||
cove: cove.numero_cove
|
||||
},
|
||||
pedimento: {
|
||||
id: pedimento.id,
|
||||
pedimento: pedimento.pedimento,
|
||||
pedimento_app: pedimento.pedimento_app,
|
||||
aduana: pedimento.aduana,
|
||||
patente: pedimento.patente,
|
||||
organizacion: pedimento.organizacion,
|
||||
regimen: pedimento.regimen || "test",
|
||||
clave_pedimento: pedimento.clave_pedimento || "test",
|
||||
numero_operacion: pedimento.numero_operacion || "test"
|
||||
},
|
||||
credencial: {
|
||||
id: credencial.id,
|
||||
user: credencial.usuario,
|
||||
password: credencial.password,
|
||||
efirma: credencial.efirma,
|
||||
key: credencial.key,
|
||||
cer: credencial.cer,
|
||||
is_active: credencial.is_active,
|
||||
organizacion: credencial.organizacion
|
||||
}
|
||||
};
|
||||
|
||||
// Verificar si MICROSERVICE_URL_2 está definido
|
||||
if (!MICROSERVICE_URL_2) {
|
||||
throw new Error('La variable de entorno VITE_EFC_MICROSERVICE_URL_2 no está configurada');
|
||||
}
|
||||
|
||||
const response = await fetchWithAuth(`${MICROSERVICE_URL_2}/services/cove/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
showMessage('COVE procesado correctamente', 'success');
|
||||
} else {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || 'Error al procesar el COVE');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error procesando COVE:', error);
|
||||
showMessage(`Error al procesar el COVE: ${error.message}`, 'error');
|
||||
} finally {
|
||||
setProcessingCove(null);
|
||||
}
|
||||
};
|
||||
|
||||
// Función para procesar Acuse de COVE
|
||||
const handleAcuseCoveProcess = async (cove) => {
|
||||
setProcessingAcuseCove(cove.id);
|
||||
|
||||
try {
|
||||
// Obtener credenciales para el contribuyente del pedimento
|
||||
const credencialesList = await fetchCredenciales(pedimento.contribuyente);
|
||||
|
||||
if (credencialesList.length === 0) {
|
||||
showMessage('No se encontraron credenciales VUCEM para este contribuyente', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Usar la primera credencial activa disponible
|
||||
const credencial = credencialesList.find(c => c.is_active) || credencialesList[0];
|
||||
|
||||
const requestBody = {
|
||||
cove: {
|
||||
id: cove.id,
|
||||
cove: cove.numero_cove
|
||||
},
|
||||
pedimento: {
|
||||
id: pedimento.id,
|
||||
pedimento: pedimento.pedimento,
|
||||
pedimento_app: pedimento.pedimento_app,
|
||||
aduana: pedimento.aduana,
|
||||
patente: pedimento.patente,
|
||||
organizacion: pedimento.organizacion,
|
||||
regimen: pedimento.regimen || "test",
|
||||
clave_pedimento: pedimento.clave_pedimento || "test",
|
||||
numero_operacion: pedimento.numero_operacion || "test"
|
||||
},
|
||||
credencial: {
|
||||
id: credencial.id,
|
||||
user: credencial.usuario,
|
||||
password: credencial.password,
|
||||
efirma: credencial.efirma,
|
||||
key: credencial.key,
|
||||
cer: credencial.cer,
|
||||
is_active: credencial.is_active,
|
||||
organizacion: credencial.organizacion
|
||||
}
|
||||
};
|
||||
|
||||
// Verificar si MICROSERVICE_URL_2 está definido
|
||||
if (!MICROSERVICE_URL_2) {
|
||||
throw new Error('La variable de entorno VITE_EFC_MICROSERVICE_URL_2 no está configurada');
|
||||
}
|
||||
|
||||
const response = await fetchWithAuth(`${MICROSERVICE_URL_2}/services/acuse/cove/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
showMessage('Acuse de COVE procesado correctamente', 'success');
|
||||
} else {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || 'Error al procesar el acuse de COVE');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error procesando acuse de COVE:', error);
|
||||
showMessage(`Error al procesar el acuse de COVE: ${error.message}`, 'error');
|
||||
} finally {
|
||||
setProcessingAcuseCove(null);
|
||||
}
|
||||
};
|
||||
|
||||
// Función para procesar EDoc
|
||||
const handleEdocProcess = async (edoc) => {
|
||||
setProcessingEdoc(edoc.id);
|
||||
|
||||
try {
|
||||
// Obtener credenciales para el contribuyente del pedimento
|
||||
const credencialesList = await fetchCredenciales(pedimento.contribuyente);
|
||||
|
||||
if (credencialesList.length === 0) {
|
||||
showMessage('No se encontraron credenciales VUCEM para este contribuyente', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Usar la primera credencial activa disponible
|
||||
const credencial = credencialesList.find(c => c.is_active) || credencialesList[0];
|
||||
|
||||
const requestBody = {
|
||||
edoc: {
|
||||
id: edoc.id,
|
||||
numero_edocument: edoc.numero_edocument
|
||||
},
|
||||
idEDocument: edoc.numero_edocument,
|
||||
pedimento: {
|
||||
id: pedimento.id,
|
||||
pedimento: pedimento.pedimento,
|
||||
pedimento_app: pedimento.pedimento_app,
|
||||
aduana: pedimento.aduana,
|
||||
patente: pedimento.patente,
|
||||
organizacion: pedimento.organizacion,
|
||||
regimen: pedimento.regimen || "test",
|
||||
clave_pedimento: pedimento.clave_pedimento || "test",
|
||||
numero_operacion: pedimento.numero_operacion || "test"
|
||||
},
|
||||
credencial: {
|
||||
id: credencial.id,
|
||||
user: credencial.usuario,
|
||||
password: credencial.password,
|
||||
efirma: credencial.efirma,
|
||||
key: credencial.key,
|
||||
cer: credencial.cer,
|
||||
is_active: credencial.is_active,
|
||||
organizacion: credencial.organizacion
|
||||
}
|
||||
};
|
||||
|
||||
// Verificar si MICROSERVICE_URL_2 está definido
|
||||
if (!MICROSERVICE_URL_2) {
|
||||
throw new Error('La variable de entorno VITE_EFC_MICROSERVICE_URL_2 no está configurada');
|
||||
}
|
||||
|
||||
const response = await fetchWithAuth(`${MICROSERVICE_URL_2}/services/download/edoc/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
showMessage('EDoc procesado correctamente', 'success');
|
||||
} else {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || 'Error al procesar el EDoc');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error procesando EDoc:', error);
|
||||
showMessage(`Error al procesar el EDoc: ${error.message}`, 'error');
|
||||
} finally {
|
||||
setProcessingEdoc(null);
|
||||
}
|
||||
};
|
||||
|
||||
// Función para procesar Acuse de EDoc
|
||||
const handleAcuseEdocProcess = async (edoc) => {
|
||||
setProcessingAcuseEdoc(edoc.id);
|
||||
|
||||
try {
|
||||
// Obtener credenciales para el contribuyente del pedimento
|
||||
const credencialesList = await fetchCredenciales(pedimento.contribuyente);
|
||||
|
||||
if (credencialesList.length === 0) {
|
||||
showMessage('No se encontraron credenciales VUCEM para este contribuyente', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Usar la primera credencial activa disponible
|
||||
const credencial = credencialesList.find(c => c.is_active) || credencialesList[0];
|
||||
|
||||
const requestBody = {
|
||||
edoc: {
|
||||
id: edoc.id,
|
||||
numero_edocument: edoc.numero_edocument
|
||||
},
|
||||
idEDocument: edoc.numero_edocument,
|
||||
pedimento: {
|
||||
id: pedimento.id,
|
||||
pedimento: pedimento.pedimento,
|
||||
pedimento_app: pedimento.pedimento_app,
|
||||
aduana: pedimento.aduana,
|
||||
patente: pedimento.patente,
|
||||
organizacion: pedimento.organizacion,
|
||||
regimen: pedimento.regimen || "test",
|
||||
clave_pedimento: pedimento.clave_pedimento || "test",
|
||||
numero_operacion: pedimento.numero_operacion || "test"
|
||||
},
|
||||
credencial: {
|
||||
id: credencial.id,
|
||||
user: credencial.usuario,
|
||||
password: credencial.password,
|
||||
efirma: credencial.efirma,
|
||||
key: credencial.key,
|
||||
cer: credencial.cer,
|
||||
is_active: credencial.is_active,
|
||||
organizacion: credencial.organizacion
|
||||
}
|
||||
};
|
||||
|
||||
// Verificar si MICROSERVICE_URL_2 está definido
|
||||
if (!MICROSERVICE_URL_2) {
|
||||
throw new Error('La variable de entorno VITE_EFC_MICROSERVICE_URL_2 no está configurada');
|
||||
}
|
||||
|
||||
const response = await fetchWithAuth(`${MICROSERVICE_URL_2}/services/acuse/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
showMessage('Acuse de EDoc procesado correctamente', 'success');
|
||||
} else {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || 'Error al procesar el acuse de EDoc');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error procesando acuse de EDoc:', error);
|
||||
showMessage(`Error al procesar el acuse de EDoc: ${error.message}`, 'error');
|
||||
} finally {
|
||||
setProcessingAcuseEdoc(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEdocRequest = async (edoc) => {
|
||||
console.log('Request edoc:', edoc);
|
||||
showMessage(`Procesando petición para EDocs #${edoc.numero_edocument}...`, 'info');
|
||||
@@ -1231,9 +1628,7 @@ export default function PedimentoDetail() {
|
||||
};
|
||||
|
||||
const handlePartidaRequest = async (partida) => {
|
||||
console.log('Request partida:', partida);
|
||||
showMessage(`Procesando petición para partida #${partida.numero_partida}...`, 'info');
|
||||
// Aquí implementarías la lógica de petición específica para partidas
|
||||
await handlePartidaProcess(partida);
|
||||
};
|
||||
|
||||
// Funciones de selección para partidas
|
||||
@@ -2160,17 +2555,28 @@ export default function PedimentoDetail() {
|
||||
{/* Botón Petición (solo activo si está pendiente) */}
|
||||
<button
|
||||
onClick={() => handlePartidaRequest(partida)}
|
||||
disabled={partida.descargado}
|
||||
disabled={partida.descargado || processingPartida === partida.id}
|
||||
className={`p-1 rounded transition-colors ${
|
||||
partida.descargado
|
||||
partida.descargado || processingPartida === partida.id
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: 'text-purple-600 hover:text-purple-900'
|
||||
}`}
|
||||
title={partida.descargado ? 'No disponible - Ya descargado' : 'Procesar petición'}
|
||||
title={
|
||||
processingPartida === partida.id ? 'Procesando partida...' :
|
||||
partida.descargado ? 'No disponible - Ya descargado' :
|
||||
'Procesar petición'
|
||||
}
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 4H6a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-2m-4-1v8m0 0l3-3m-3 3L9 8m-5 5h2.586a1 1 0 01.707.293l2.414 2.414a1 1 0 00.707.293H20" />
|
||||
</svg>
|
||||
{processingPartida === partida.id ? (
|
||||
<svg className="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 4H6a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-2m-4-1v8m0 0l3-3m-3 3L9 8m-5 5h2.586a1 1 0 01.707.293l2.414 2.414a1 1 0 00.707.293H20" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
@@ -2409,20 +2815,52 @@ export default function PedimentoDetail() {
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<div className="flex items-center justify-end space-x-2">
|
||||
{/* Botón Procesar petición (solo activo si está pendiente) */}
|
||||
{/* Botón COVE */}
|
||||
<button
|
||||
onClick={() => handleCoveRequest(cove)}
|
||||
disabled={cove.cove_descargado && cove.acuse_cove_descargado}
|
||||
onClick={() => handleCoveProcess(cove)}
|
||||
disabled={cove.cove_descargado || processingCove === cove.id}
|
||||
className={`p-1 rounded transition-colors ${
|
||||
cove.cove_descargado && cove.acuse_cove_descargado
|
||||
cove.cove_descargado
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: 'text-purple-600 hover:text-purple-900'
|
||||
: processingCove === cove.id
|
||||
? 'text-blue-400 cursor-not-allowed'
|
||||
: 'text-blue-600 hover:text-blue-900'
|
||||
}`}
|
||||
title={(cove.cove_descargado && cove.acuse_cove_descargado) ? 'No disponible - Ya descargado' : 'Procesar petición'}
|
||||
title={cove.cove_descargado ? 'COVE ya descargado' : processingCove === cove.id ? 'Procesando COVE...' : 'Procesar COVE'}
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 4H6a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-2m-4-1v8m0 0l3-3m-3 3L9 8m-5 5h2.586a1 1 0 01.707.293l2.414 2.414a1 1 0 00.707.293H20" />
|
||||
</svg>
|
||||
{processingCove === cove.id ? (
|
||||
<svg className="w-4 h-4 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h1m4 0h1m-6 4h8m-10-4a9 9 0 1118 0 9 9 0 01-18 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* Botón Acuse de COVE */}
|
||||
<button
|
||||
onClick={() => handleAcuseCoveProcess(cove)}
|
||||
disabled={cove.acuse_cove_descargado || processingAcuseCove === cove.id}
|
||||
className={`p-1 rounded transition-colors ${
|
||||
cove.acuse_cove_descargado
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: processingAcuseCove === cove.id
|
||||
? 'text-green-400 cursor-not-allowed'
|
||||
: 'text-green-600 hover:text-green-900'
|
||||
}`}
|
||||
title={cove.acuse_cove_descargado ? 'Acuse de COVE ya descargado' : processingAcuseCove === cove.id ? 'Procesando Acuse de COVE...' : 'Procesar Acuse de COVE'}
|
||||
>
|
||||
{processingAcuseCove === cove.id ? (
|
||||
<svg className="w-4 h-4 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
@@ -2712,20 +3150,52 @@ export default function PedimentoDetail() {
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<div className="flex items-center justify-end space-x-2">
|
||||
{/* Botón Procesar petición (solo activo si está pendiente) */}
|
||||
{/* Botón EDoc */}
|
||||
<button
|
||||
onClick={() => handleEdocRequest(edoc)}
|
||||
disabled={edoc.edocument_descargado && edoc.acuse_descargado}
|
||||
onClick={() => handleEdocProcess(edoc)}
|
||||
disabled={edoc.edocument_descargado || processingEdoc === edoc.id}
|
||||
className={`p-1 rounded transition-colors ${
|
||||
edoc.edocument_descargado && edoc.acuse_descargado
|
||||
edoc.edocument_descargado
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: 'text-purple-600 hover:text-purple-900'
|
||||
: processingEdoc === edoc.id
|
||||
? 'text-blue-400 cursor-not-allowed'
|
||||
: 'text-blue-600 hover:text-blue-900'
|
||||
}`}
|
||||
title={(edoc.edocument_descargado && edoc.acuse_descargado) ? 'No disponible - Ya descargado' : 'Procesar petición'}
|
||||
title={edoc.edocument_descargado ? 'EDoc ya descargado' : processingEdoc === edoc.id ? 'Procesando EDoc...' : 'Procesar EDoc'}
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 4H6a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-2m-4-1v8m0 0l3-3m-3 3L9 8m-5 5h2.586a1 1 0 01.707.293l2.414 2.414a1 1 0 00.707.293H20" />
|
||||
</svg>
|
||||
{processingEdoc === edoc.id ? (
|
||||
<svg className="w-4 h-4 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* Botón Acuse de EDoc */}
|
||||
<button
|
||||
onClick={() => handleAcuseEdocProcess(edoc)}
|
||||
disabled={edoc.acuse_descargado || processingAcuseEdoc === edoc.id}
|
||||
className={`p-1 rounded transition-colors ${
|
||||
edoc.acuse_descargado
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: processingAcuseEdoc === edoc.id
|
||||
? 'text-green-400 cursor-not-allowed'
|
||||
: 'text-green-600 hover:text-green-900'
|
||||
}`}
|
||||
title={edoc.acuse_descargado ? 'Acuse de EDoc ya descargado' : processingAcuseEdoc === edoc.id ? 'Procesando Acuse de EDoc...' : 'Procesar Acuse de EDoc'}
|
||||
>
|
||||
{processingAcuseEdoc === edoc.id ? (
|
||||
<svg className="w-4 h-4 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
@@ -2991,70 +3461,82 @@ export default function PedimentoDetail() {
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
||||
<div className="flex items-center space-x-2">
|
||||
{/* Botón Ejecutar Servicio - solo para estados Pendiente o Error */}
|
||||
{(proceso.estado === 1 || proceso.estado === 4) && (
|
||||
<button
|
||||
onClick={() => handleEjecutarServicio(proceso)}
|
||||
disabled={executingId === proceso.id}
|
||||
className={`inline-flex items-center px-3 py-1.5 border border-transparent text-xs font-medium rounded-md text-white transition-colors duration-200 ${
|
||||
executingId === proceso.id
|
||||
? 'bg-gray-400 cursor-not-allowed'
|
||||
: 'bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500'
|
||||
}`}
|
||||
>
|
||||
{executingId === proceso.id ? (
|
||||
<>
|
||||
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
Ejecutando...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<svg className="-ml-1 mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h1m4 0h1M9 16h1m4 0h1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
Ejecutar
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
{/* Botón Play (Ejecutar Servicio) */}
|
||||
<button
|
||||
onClick={() => handleEjecutarServicio(proceso)}
|
||||
disabled={
|
||||
executingId === proceso.id ||
|
||||
proceso.estado === 2 || // En Proceso
|
||||
proceso.estado === 3 || // Completado
|
||||
proceso.estado === 5 // Cancelado
|
||||
}
|
||||
className={`inline-flex items-center p-2 border border-transparent rounded-md transition-colors duration-200 ${
|
||||
executingId === proceso.id ||
|
||||
proceso.estado === 2 ||
|
||||
proceso.estado === 3 ||
|
||||
proceso.estado === 5
|
||||
? 'bg-gray-200 text-gray-400 cursor-not-allowed'
|
||||
: 'bg-green-100 text-green-700 hover:bg-green-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500'
|
||||
}`}
|
||||
title={
|
||||
executingId === proceso.id ? 'Ejecutando...' :
|
||||
proceso.estado === 2 ? 'No disponible - En proceso' :
|
||||
proceso.estado === 3 ? 'No disponible - Completado' :
|
||||
proceso.estado === 5 ? 'No disponible - Cancelado' :
|
||||
'Ejecutar servicio'
|
||||
}
|
||||
>
|
||||
{executingId === proceso.id ? (
|
||||
<svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M8 5v14l11-7z"/>
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* Botón Pasar a Espera - solo para estados En Proceso, Completado o Error */}
|
||||
{(proceso.estado === 2 || proceso.estado === 3 || proceso.estado === 4) && (
|
||||
<button
|
||||
onClick={() => handlePasarAEspera(proceso)}
|
||||
disabled={changingStateId === proceso.id}
|
||||
className={`inline-flex items-center px-3 py-1.5 border border-transparent text-xs font-medium rounded-md text-white transition-colors duration-200 ${
|
||||
changingStateId === proceso.id
|
||||
? 'bg-gray-400 cursor-not-allowed'
|
||||
: 'bg-yellow-600 hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500'
|
||||
}`}
|
||||
>
|
||||
{changingStateId === proceso.id ? (
|
||||
<>
|
||||
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
Cambiando...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<svg className="-ml-1 mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
A Espera
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Mostrar texto si no hay acciones disponibles */}
|
||||
{proceso.estado !== 1 && proceso.estado !== 2 && proceso.estado !== 3 && proceso.estado !== 4 && (
|
||||
<span className="text-xs text-gray-400 italic">Sin acciones</span>
|
||||
)}
|
||||
{/* Botón Refresh (Pasar a Espera) */}
|
||||
<button
|
||||
onClick={() => handlePasarAEspera(proceso)}
|
||||
disabled={
|
||||
changingStateId === proceso.id ||
|
||||
proceso.estado === 1 || // Pendiente
|
||||
proceso.estado === 2 || // En Proceso
|
||||
proceso.estado === 3 || // Completado
|
||||
proceso.estado === 5 // Cancelado
|
||||
}
|
||||
className={`inline-flex items-center p-2 border border-transparent rounded-md transition-colors duration-200 ${
|
||||
changingStateId === proceso.id ||
|
||||
proceso.estado === 1 ||
|
||||
proceso.estado === 2 ||
|
||||
proceso.estado === 3 ||
|
||||
proceso.estado === 5
|
||||
? 'bg-gray-200 text-gray-400 cursor-not-allowed'
|
||||
: 'bg-yellow-100 text-yellow-700 hover:bg-yellow-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500'
|
||||
}`}
|
||||
title={
|
||||
changingStateId === proceso.id ? 'Cambiando estado...' :
|
||||
proceso.estado === 1 ? 'No disponible - Use Play para ejecutar' :
|
||||
proceso.estado === 2 ? 'No disponible - En proceso' :
|
||||
proceso.estado === 3 ? 'No disponible - Completado' :
|
||||
proceso.estado === 5 ? 'No disponible - Cancelado' :
|
||||
'Pasar a espera'
|
||||
}
|
||||
>
|
||||
{changingStateId === proceso.id ? (
|
||||
<svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user