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_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=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 API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||||
const MICROSERVICE_URL = import.meta.env.VITE_EFC_MICROSERVICE_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)
|
// Funciones auxiliares para estados y servicios (copiadas de procesos.js)
|
||||||
const getEstadoLabel = (estado) => {
|
const getEstadoLabel = (estado) => {
|
||||||
@@ -196,6 +197,108 @@ export default function PedimentoDetail() {
|
|||||||
const [downloadingPartidas, setDownloadingPartidas] = useState(false);
|
const [downloadingPartidas, setDownloadingPartidas] = useState(false);
|
||||||
const [downloadingAllPartidas, setDownloadingAllPartidas] = 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
|
// Función para obtener partidas
|
||||||
const fetchPedimentoPartidas = async (page = 1, pageSize = 10, filters = {}) => {
|
const fetchPedimentoPartidas = async (page = 1, pageSize = 10, filters = {}) => {
|
||||||
console.log('fetchPedimentoPartidas called with:', { page, pageSize, 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
|
// 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) => {
|
const handleEdocRequest = async (edoc) => {
|
||||||
console.log('Request edoc:', edoc);
|
console.log('Request edoc:', edoc);
|
||||||
showMessage(`Procesando petición para EDocs #${edoc.numero_edocument}...`, 'info');
|
showMessage(`Procesando petición para EDocs #${edoc.numero_edocument}...`, 'info');
|
||||||
@@ -1231,9 +1628,7 @@ export default function PedimentoDetail() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handlePartidaRequest = async (partida) => {
|
const handlePartidaRequest = async (partida) => {
|
||||||
console.log('Request partida:', partida);
|
await handlePartidaProcess(partida);
|
||||||
showMessage(`Procesando petición para partida #${partida.numero_partida}...`, 'info');
|
|
||||||
// Aquí implementarías la lógica de petición específica para partidas
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Funciones de selección para partidas
|
// Funciones de selección para partidas
|
||||||
@@ -2160,17 +2555,28 @@ export default function PedimentoDetail() {
|
|||||||
{/* Botón Petición (solo activo si está pendiente) */}
|
{/* Botón Petición (solo activo si está pendiente) */}
|
||||||
<button
|
<button
|
||||||
onClick={() => handlePartidaRequest(partida)}
|
onClick={() => handlePartidaRequest(partida)}
|
||||||
disabled={partida.descargado}
|
disabled={partida.descargado || processingPartida === partida.id}
|
||||||
className={`p-1 rounded transition-colors ${
|
className={`p-1 rounded transition-colors ${
|
||||||
partida.descargado
|
partida.descargado || processingPartida === partida.id
|
||||||
? 'text-gray-400 cursor-not-allowed'
|
? 'text-gray-400 cursor-not-allowed'
|
||||||
: 'text-purple-600 hover:text-purple-900'
|
: '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'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
|
{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">
|
<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" />
|
<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>
|
</svg>
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -2409,20 +2815,52 @@ export default function PedimentoDetail() {
|
|||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
<div className="flex items-center justify-end space-x-2">
|
<div className="flex items-center justify-end space-x-2">
|
||||||
{/* Botón Procesar petición (solo activo si está pendiente) */}
|
{/* Botón COVE */}
|
||||||
<button
|
<button
|
||||||
onClick={() => handleCoveRequest(cove)}
|
onClick={() => handleCoveProcess(cove)}
|
||||||
disabled={cove.cove_descargado && cove.acuse_cove_descargado}
|
disabled={cove.cove_descargado || processingCove === cove.id}
|
||||||
className={`p-1 rounded transition-colors ${
|
className={`p-1 rounded transition-colors ${
|
||||||
cove.cove_descargado && cove.acuse_cove_descargado
|
cove.cove_descargado
|
||||||
? 'text-gray-400 cursor-not-allowed'
|
? '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">
|
{processingCove === cove.id ? (
|
||||||
<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 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>
|
||||||
|
) : (
|
||||||
|
<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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -2712,20 +3150,52 @@ export default function PedimentoDetail() {
|
|||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
<div className="flex items-center justify-end space-x-2">
|
<div className="flex items-center justify-end space-x-2">
|
||||||
{/* Botón Procesar petición (solo activo si está pendiente) */}
|
{/* Botón EDoc */}
|
||||||
<button
|
<button
|
||||||
onClick={() => handleEdocRequest(edoc)}
|
onClick={() => handleEdocProcess(edoc)}
|
||||||
disabled={edoc.edocument_descargado && edoc.acuse_descargado}
|
disabled={edoc.edocument_descargado || processingEdoc === edoc.id}
|
||||||
className={`p-1 rounded transition-colors ${
|
className={`p-1 rounded transition-colors ${
|
||||||
edoc.edocument_descargado && edoc.acuse_descargado
|
edoc.edocument_descargado
|
||||||
? 'text-gray-400 cursor-not-allowed'
|
? '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">
|
{processingEdoc === edoc.id ? (
|
||||||
<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 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>
|
||||||
|
) : (
|
||||||
|
<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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -2991,70 +3461,82 @@ export default function PedimentoDetail() {
|
|||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
{/* Botón Ejecutar Servicio - solo para estados Pendiente o Error */}
|
{/* Botón Play (Ejecutar Servicio) */}
|
||||||
{(proceso.estado === 1 || proceso.estado === 4) && (
|
|
||||||
<button
|
<button
|
||||||
onClick={() => handleEjecutarServicio(proceso)}
|
onClick={() => handleEjecutarServicio(proceso)}
|
||||||
disabled={executingId === proceso.id}
|
disabled={
|
||||||
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 ||
|
||||||
executingId === proceso.id
|
proceso.estado === 2 || // En Proceso
|
||||||
? 'bg-gray-400 cursor-not-allowed'
|
proceso.estado === 3 || // Completado
|
||||||
: 'bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500'
|
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 ? (
|
{executingId === proceso.id ? (
|
||||||
<>
|
<svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||||
<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>
|
<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>
|
<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>
|
||||||
Ejecutando...
|
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<svg className="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
||||||
<svg className="-ml-1 mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<path d="M8 5v14l11-7z"/>
|
||||||
<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>
|
</svg>
|
||||||
Ejecutar
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Botón Pasar a Espera - solo para estados En Proceso, Completado o Error */}
|
{/* Botón Refresh (Pasar a Espera) */}
|
||||||
{(proceso.estado === 2 || proceso.estado === 3 || proceso.estado === 4) && (
|
|
||||||
<button
|
<button
|
||||||
onClick={() => handlePasarAEspera(proceso)}
|
onClick={() => handlePasarAEspera(proceso)}
|
||||||
disabled={changingStateId === proceso.id}
|
disabled={
|
||||||
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 ||
|
||||||
changingStateId === proceso.id
|
proceso.estado === 1 || // Pendiente
|
||||||
? 'bg-gray-400 cursor-not-allowed'
|
proceso.estado === 2 || // En Proceso
|
||||||
: 'bg-yellow-600 hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500'
|
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 ? (
|
{changingStateId === proceso.id ? (
|
||||||
<>
|
<svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||||
<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>
|
<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>
|
<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>
|
||||||
Cambiando...
|
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<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="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" />
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
||||||
</svg>
|
</svg>
|
||||||
A Espera
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</button>
|
</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>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user