mirror of
https://git.imnavajas.es/jjimenez/safekat.git
synced 2025-07-25 22:52:08 +00:00
Primera version del importador RAMA
This commit is contained in:
@ -18,6 +18,7 @@ $routes->group('importador', ['namespace' => 'App\Controllers\Importadores'], fu
|
||||
* AJAX
|
||||
*========================**/
|
||||
$routes->post('validar-fila', 'ImportadorCatalogo::validarFila');
|
||||
$routes->post('importar-fila', 'ImportadorCatalogo::importarFila');
|
||||
|
||||
|
||||
});
|
||||
|
||||
@ -4,8 +4,7 @@ namespace App\Controllers\Importadores;
|
||||
use App\Controllers\BaseResourceController;
|
||||
use App\Entities\Catalogo\CatalogoLibroEntity;
|
||||
use App\Models\Catalogo\CatalogoLibroModel;
|
||||
use App\Models\Clientes\ClienteModel;
|
||||
use Hermawan\DataTables\DataTable;
|
||||
use App\Controllers\Presupuestos\Presupuestocliente;
|
||||
|
||||
class ImportadorCatalogo extends BaseResourceController
|
||||
{
|
||||
@ -57,134 +56,6 @@ class ImportadorCatalogo extends BaseResourceController
|
||||
}
|
||||
|
||||
|
||||
public function add()
|
||||
{
|
||||
|
||||
if ($this->request->getPost()):
|
||||
|
||||
$postData = $this->request->getPost();
|
||||
|
||||
$sanitizedData = $this->sanitized($postData, true);
|
||||
|
||||
$sanitizedData['user_created_id'] = auth()->user()->id;
|
||||
unset($sanitizedData['isk']);
|
||||
|
||||
$noException = true;
|
||||
if ($successfulResult = $this->canValidate()):
|
||||
|
||||
if ($this->canValidate()):
|
||||
try {
|
||||
$successfulResult = $this->model->skipValidation(true)->save($sanitizedData);
|
||||
} catch (\Exception $e) {
|
||||
$noException = false;
|
||||
$this->dealWithException($e);
|
||||
}
|
||||
else:
|
||||
$this->viewData['errorMessage'] = lang('Basic.global.formErr1', [lang('Basic.global.record')]);
|
||||
$this->session->setFlashdata('formErrors', $this->model->errors());
|
||||
endif;
|
||||
|
||||
$thenRedirect = true; // Change this to false if you want your user to stay on the form after submission
|
||||
endif;
|
||||
|
||||
if ($noException && $successfulResult):
|
||||
|
||||
$id = $this->model->db->insertID();
|
||||
|
||||
$message = lang('Basic.global.saveSuccess', [lang('Basic.global.record')]) . '.';
|
||||
|
||||
if ($thenRedirect):
|
||||
if (!empty($this->indexRoute)):
|
||||
return redirect()->to(route_to($this->indexRoute))->with('sweet-success', $message);
|
||||
else:
|
||||
return $this->redirect2listView('sweet-success', $message);
|
||||
endif;
|
||||
else:
|
||||
$this->session->setFlashData('sweet-success', $message);
|
||||
endif;
|
||||
|
||||
endif; // $noException && $successfulResult
|
||||
|
||||
endif; // ($requestMethod === 'post')
|
||||
|
||||
$this->viewData['catalogoLibrosEntity'] = isset($sanitizedData) ? new CatalogoLibroEntity($sanitizedData) : new CatalogoLibroEntity();
|
||||
$this->viewData['formAction'] = route_to('catalogoLibrosAdd');
|
||||
$this->viewData['boxTitle'] = lang('Basic.global.addNew') . ' ' . lang('Catalogo.moduleTitle') . ' ' . lang('Basic.global.addNewSuffix');
|
||||
|
||||
return $this->displayForm(__METHOD__);
|
||||
} // end function add()
|
||||
|
||||
public function edit($requestedId = null)
|
||||
{
|
||||
|
||||
if ($requestedId == null):
|
||||
return $this->redirect2listView();
|
||||
endif;
|
||||
$id = filter_var($requestedId, FILTER_SANITIZE_URL);
|
||||
$catalogoLibrosEntity = $this->model->find($id);
|
||||
|
||||
if ($catalogoLibrosEntity == false):
|
||||
$message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Catalogo.pais')), $id]);
|
||||
return $this->redirect2listView('sweet-error', $message);
|
||||
endif;
|
||||
|
||||
if ($this->request->getPost()):
|
||||
|
||||
$postData = $this->request->getPost();
|
||||
$sanitizedData = $this->sanitized($postData, true);
|
||||
unset($sanitizedData['isk']);
|
||||
$sanitizedData['user_update_id'] = auth()->user()->id;
|
||||
|
||||
$noException = true;
|
||||
|
||||
if ($successfulResult = $this->canValidate()): // if ($successfulResult = $this->validate($this->formValidationRules) ) :
|
||||
|
||||
|
||||
if ($this->canValidate()):
|
||||
try {
|
||||
$successfulResult = $this->model->skipValidation(true)->update($id, $sanitizedData);
|
||||
} catch (\Exception $e) {
|
||||
$noException = false;
|
||||
$this->dealWithException($e);
|
||||
}
|
||||
else:
|
||||
$this->viewData['warningMessage'] = lang('Basic.global.formErr1', [mb_strtolower(lang('Catalogo.catalogo'))]);
|
||||
$this->session->setFlashdata('formErrors', $this->model->errors());
|
||||
|
||||
endif;
|
||||
|
||||
$catalogoLibrosEntity->fill($sanitizedData);
|
||||
$thenRedirect = false;
|
||||
endif;
|
||||
|
||||
if ($noException && $successfulResult):
|
||||
$id = $catalogoLibrosEntity->id ?? $id;
|
||||
$message = lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.';
|
||||
|
||||
if ($thenRedirect):
|
||||
if (!empty($this->indexRoute)):
|
||||
return redirect()->to(route_to($this->indexRoute))->with('sweet-success', $message);
|
||||
else:
|
||||
return $this->redirect2listView('sweet-success', $message);
|
||||
endif;
|
||||
else:
|
||||
$this->session->setFlashData('sweet-success', $message);
|
||||
endif;
|
||||
|
||||
endif; // $noException && $successfulResult
|
||||
endif; // ($requestMethod === 'post')
|
||||
|
||||
|
||||
$this->viewData['catalogoLibrosEntity'] = $catalogoLibrosEntity;
|
||||
$this->viewData['formAction'] = route_to('catalogoLibrosEdit', $id);
|
||||
$this->viewData['boxTitle'] = lang('Basic.global.edit2') . ' ' . lang('Catalogo.moduleTitle') . ' ' . lang('Basic.global.edit3');
|
||||
|
||||
|
||||
return $this->displayForm(__METHOD__, $id);
|
||||
} // end function edit(...)
|
||||
|
||||
|
||||
|
||||
public function validarFila()
|
||||
{
|
||||
$json = $this->request->getJSON();
|
||||
@ -234,4 +105,244 @@ class ImportadorCatalogo extends BaseResourceController
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function importarFila()
|
||||
{
|
||||
$json = $this->request->getJSON();
|
||||
|
||||
if (!$json || !isset($json->fila[0])) {
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => 'Datos inválidos.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Mapear cada columna a una variable
|
||||
$isbn = isset($json->fila[0]) ? trim($json->fila[0]) : null;
|
||||
$refCliente = isset($json->fila[1]) ? trim($json->fila[1]) : null;
|
||||
//$descripcion = isset($json->fila[2]) ? trim($json->fila[2]) : null;
|
||||
$tirada = isset($json->fila[3]) ? (float) $json->fila[3] : null;
|
||||
//$precio_compra = isset($json->fila[4]) ? (float) $json->fila[4] : null;
|
||||
|
||||
if (empty($isbn)) {
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => 'Input vacío o no proporcionado.'
|
||||
]);
|
||||
}
|
||||
|
||||
$catalogoModel = new CatalogoLibroModel();
|
||||
|
||||
// 1. Buscar por ISBN exacto
|
||||
$libro = $catalogoModel->where('isbn', $isbn)->first();
|
||||
|
||||
// 2. Si no, buscar por EAN sin guiones
|
||||
if (!$libro) {
|
||||
$eanLimpio = str_replace('-', '', $isbn);
|
||||
|
||||
$libro = $catalogoModel->where('REPLACE(ean, "-", "")', $eanLimpio)->first();
|
||||
}
|
||||
|
||||
if (!$libro) {
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => 'No se encontró el libro en el catálogo.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Aquí ya tenemos el libro correcto.
|
||||
// Ahora se prepara la "inserción" o el "registro" a importar
|
||||
// Variables intermedias
|
||||
$colorPaginas = (int) ($libro->color_paginas ?? 0);
|
||||
$negroPaginas = (int) ($libro->negro_paginas ?? 0);
|
||||
$papelInteriorDiferente = ($colorPaginas > 0 && $negroPaginas > 0) ? 1 : 0;
|
||||
|
||||
// --- Interior (lo que cambiamos ahora)
|
||||
if ($papelInteriorDiferente) {
|
||||
// Mixto: páginas en negro + color
|
||||
$interior = [
|
||||
'papelInterior' => [
|
||||
'negro' => $libro->negro_papel_id,
|
||||
'color' => $libro->color_papel_id,
|
||||
],
|
||||
'gramajeInterior' => [
|
||||
'negro' => $libro->negro_gramaje,
|
||||
'color' => $libro->color_gramaje,
|
||||
]
|
||||
];
|
||||
} else {
|
||||
// SOLO un tipo: negro O color
|
||||
$colorPaginas = (int)($libro->color_paginas ?? 0);
|
||||
$negroPaginas = (int)($libro->negro_paginas ?? 0);
|
||||
|
||||
if ($colorPaginas > 0 && $negroPaginas == 0) {
|
||||
// Libro completamente en color
|
||||
$interior = [
|
||||
'papelInterior' => $libro->color_papel_id,
|
||||
'gramajeInterior' => $libro->color_gramaje,
|
||||
];
|
||||
} else {
|
||||
// Libro completamente en blanco y negro
|
||||
$interior = [
|
||||
'papelInterior' => $libro->negro_papel_id,
|
||||
'gramajeInterior' => $libro->negro_gramaje,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Sobrecubierta
|
||||
$sobrecubierta = [];
|
||||
if (!is_null($libro->sobrecubierta_paginas)) {
|
||||
$sobrecubierta['papel'] = $libro->sobrecubierta_papel_id;
|
||||
$sobrecubierta['gramaje'] = $libro->sobrecubierta_gramaje;
|
||||
$sobrecubierta['solapas'] = $libro->sobrecubierta_solapas;
|
||||
$sobrecubierta['acabado'] = $libro->sobrecubierta_acabado_id;
|
||||
}
|
||||
|
||||
|
||||
$dataToImport = [
|
||||
'selectedTirada' => $tirada,
|
||||
'datosCabecera' => [
|
||||
'titulo' => $libro->titulo,
|
||||
'autor' => $libro->autor,
|
||||
'isbn' => $isbn,
|
||||
'coleccion' => $libro->coleccion,
|
||||
'referenciaCliente' => $refCliente
|
||||
],
|
||||
'tirada' => array_values(array_filter([
|
||||
$tirada,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
])),
|
||||
'tamanio' => [
|
||||
'ancho' => $libro->ancho,
|
||||
'alto' => $libro->alto
|
||||
],
|
||||
'tipo' => "",
|
||||
'tipo_presupuesto_id' => $libro->encuadernacion_id,
|
||||
'clienteId' => 251,
|
||||
'isColor' => (in_array(strtolower($libro->tipo_impresion), ['color', 'colorhq']) ? 1 : 0),
|
||||
'isHq' => (in_array(strtolower($libro->tipo_impresion), ['negrohq', 'colorhq']) ? 1 : 0),
|
||||
'paginas' => $libro->paginas,
|
||||
'paginasColor' => $colorPaginas,
|
||||
'papelInteriorDiferente' => $papelInteriorDiferente,
|
||||
'paginasCuadernillo' => 32,
|
||||
|
||||
'interior' => $interior,
|
||||
|
||||
'cubierta' => [
|
||||
'papelCubierta' => $libro->cubierta_papel_id,
|
||||
'gramajeCubierta' => $libro->cubierta_gramaje,
|
||||
'solapas' => $libro->cubierta_ancho_solapas,
|
||||
'acabado' => $libro->cubierta_acabado_id,
|
||||
'cabezada' => 'WHI',
|
||||
'lomoRedondo' => 0
|
||||
],
|
||||
|
||||
'guardas' => [],
|
||||
'sobrecubierta' => $sobrecubierta,
|
||||
'faja' => [],
|
||||
|
||||
'entrega_taller' => 1,
|
||||
];
|
||||
|
||||
/*return $this->response->setJSON([
|
||||
'success' => true,
|
||||
'message' => 'Libro encontrado y preparado para importar.',
|
||||
'data' => $dataToImport
|
||||
]);*/
|
||||
|
||||
|
||||
// Procedemos a intentar guardar el presupuesto
|
||||
// Instancia de presupuesto cliente
|
||||
$presupuestocliente = new Presupuestocliente();
|
||||
try {
|
||||
$response = $presupuestocliente->guardar($dataToImport);
|
||||
|
||||
// DEBUG LINE
|
||||
//return $this->respond($response);
|
||||
|
||||
if (!isset($response['sk_id'])) {
|
||||
return $this->respond([
|
||||
'status' => 400,
|
||||
'error' => 'Missing sk_id',
|
||||
'message' => 'El identificador sk_id es requerido pero no se recibió.'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$response = [
|
||||
'status' => 200,
|
||||
'error' => null,
|
||||
'data' => [
|
||||
'sk_id' => $response['sk_id'],
|
||||
'sk_url' => $response['sk_url'] ?? null
|
||||
]
|
||||
];
|
||||
|
||||
return $this->respond($response);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
return $this->respond([
|
||||
'status' => 500,
|
||||
'error' => 'Server error',
|
||||
'message' => 'Error inesperado durante el procesado',
|
||||
'debug' => $e->getMessage()
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function guardar()
|
||||
{
|
||||
helper(['form']);
|
||||
|
||||
// Access the entire POST data
|
||||
$post_data = $this->request->getJSON(true);
|
||||
|
||||
//return $this->respond(var_dump($post_data));
|
||||
|
||||
// Instancia de presupuesto cliente
|
||||
$presupuestocliente = new Presupuestocliente();
|
||||
try {
|
||||
$response = $presupuestocliente->guardar($post_data);
|
||||
|
||||
// DEBUG LINE
|
||||
//return $this->respond($response);
|
||||
|
||||
if (!isset($response['sk_id'])) {
|
||||
return $this->respond([
|
||||
'status' => 400,
|
||||
'error' => 'Missing sk_id',
|
||||
'message' => 'El identificador sk_id es requerido pero no se recibió.'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$response = [
|
||||
'status' => 200,
|
||||
'error' => null,
|
||||
'data' => [
|
||||
'sk_id' => $response['sk_id'],
|
||||
'sk_url' => $response['sk_url'] ?? null
|
||||
]
|
||||
];
|
||||
|
||||
return $this->respond($response);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
return $this->respond([
|
||||
'status' => 500,
|
||||
'error' => 'Server error',
|
||||
'message' => 'Error inesperado durante el procesado'
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -35,40 +35,33 @@
|
||||
|
||||
<div class="col-md-12 mb-3">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="excelTable" class="table table-striped table-hover" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<input type="checkbox" id="select-all" class="form-check-input">
|
||||
</th>
|
||||
<th><?= lang('Importador.input') ?></th>
|
||||
<th><?= lang('Importador.idlinea') ?></th>
|
||||
<th><?= lang('Importador.descripcion') ?></th>
|
||||
<th><?= lang('Importador.cnt_pedida') ?></th>
|
||||
<th><?= lang('Importador.precio_compra') ?></th>
|
||||
<th class="text-nowrap" style="min-width: 120px;">
|
||||
<?= lang('Basic.global.Action') ?></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th><input type="text" class="form-control form-control-sm"
|
||||
placeholder="Filtrar..." /></th>
|
||||
<th><input type="text" class="form-control form-control-sm"
|
||||
placeholder="Filtrar..." /></th>
|
||||
<th><input type="text" class="form-control form-control-sm"
|
||||
placeholder="Filtrar..." /></th>
|
||||
<th><input type="text" class="form-control form-control-sm"
|
||||
placeholder="Filtrar..." /></th>
|
||||
<th><input type="text" class="form-control form-control-sm"
|
||||
placeholder="Filtrar..." /></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<table id="excelTable" class="table table-striped table-hover" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><input type="checkbox" id="selectAll"></th> <!-- Checkbox general -->
|
||||
<th><?= lang('Importador.input') ?></th>
|
||||
<th><?= lang('Importador.idlinea') ?></th>
|
||||
<th><?= lang('Importador.descripcion') ?></th>
|
||||
<th><?= lang('Importador.cnt_pedida') ?></th>
|
||||
<th><?= lang('Importador.precio_compra') ?></th>
|
||||
<th>Notas</th> <!-- Comentarios -->
|
||||
<th><?= lang('Basic.global.Action') ?></th>
|
||||
<!-- Acciones (importar/eliminar) -->
|
||||
</tr>
|
||||
<tr> <!-- Segunda fila para filtros -->
|
||||
<th></th> <!-- No filtro en checkbox -->
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th> <!-- No filtro en notas -->
|
||||
<th></th> <!-- No filtro en acciones -->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@ -19,6 +19,18 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
order: [[1, 'asc']]
|
||||
});
|
||||
|
||||
// Crear filtros por columna en el segundo <tr>
|
||||
$('#excelTable thead tr:eq(1) th').each(function (i) {
|
||||
if (![0, 6, 7].includes(i)) { // No poner input en Checkbox, Notas ni Acciones
|
||||
$(this).html('<input type="text" class="form-control form-control-sm" placeholder="Filtrar..." />');
|
||||
$('input', this).on('keyup change', function () {
|
||||
if (dataTable.column(i).search() !== this.value) {
|
||||
dataTable.column(i).search(this.value).draw();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('excelFile').addEventListener('change', function (e) {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
@ -64,38 +76,39 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
const rowData = TABLE_COLUMNS.map(col => data[i][headerMap[col]] ?? '');
|
||||
|
||||
// Llamar backend para validar la fila
|
||||
const isValid = await validarFila(rowData);
|
||||
const result = await validarFila(rowData);
|
||||
|
||||
let checkboxHtml = '';
|
||||
let actionBtnsHtml = '';
|
||||
let notaHtml = '';
|
||||
|
||||
if (isValid) {
|
||||
if (result.apto) {
|
||||
checkboxHtml = `<input type="checkbox" class="select-row form-check-input" checked>`;
|
||||
|
||||
notaHtml = '';
|
||||
actionBtnsHtml = `
|
||||
<div class="d-flex flex-column align-items-start">
|
||||
<button type="button" class="btn btn-outline-success btn-sm mb-1 importRow">
|
||||
<i class="fas fa-file-import me-1"></i> Importar
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm deleteRow">
|
||||
<i class="fas fa-trash-alt me-1"></i> Eliminar
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
<div class="d-flex flex-column align-items-start">
|
||||
<button type="button" class="btn btn-outline-success btn-sm mb-1 importRow">
|
||||
<i class="fas fa-file-import me-1"></i> Importar
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm deleteRow">
|
||||
<i class="fas fa-trash-alt me-1"></i> Eliminar
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
checkboxHtml = `<input type="checkbox" class="select-row form-check-input" disabled>`;
|
||||
|
||||
notaHtml = `<span class="badge bg-danger">${result.reason}</span>`;
|
||||
actionBtnsHtml = `
|
||||
<div class="d-flex flex-column align-items-start">
|
||||
<span class="badge rounded-pill bg-danger mb-2">No Apto</span>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm deleteRow">
|
||||
<i class="fas fa-trash-alt me-1"></i> Eliminar
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
<div class="d-flex flex-column align-items-start">
|
||||
<span class="badge rounded-pill bg-danger mb-2">No Apto</span>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm deleteRow">
|
||||
<i class="fas fa-trash-alt me-1"></i> Eliminar
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
rows.push([checkboxHtml, ...rowData, actionBtnsHtml]);
|
||||
rows.push([checkboxHtml, ...rowData, notaHtml, actionBtnsHtml]);
|
||||
}
|
||||
|
||||
dataTable.clear().rows.add(rows).draw();
|
||||
@ -114,11 +127,10 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
body: JSON.stringify({ fila: rowData })
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
return result.apto === true;
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Error validando fila', error);
|
||||
return false;
|
||||
return { apto: false, reason: 'Error conexión' };
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,25 +139,92 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
dataTable.row($(this).parents('tr')).remove().draw();
|
||||
});
|
||||
|
||||
$('#excelTable tbody').off('click', '.importRow').on('click', '.importRow', function () {
|
||||
const rowData = dataTable.row($(this).parents('tr')).data();
|
||||
console.log('Importar esta fila:', rowData);
|
||||
// Aquí podrías enviar sólo esta fila al servidor si quieres importar individualmente
|
||||
});
|
||||
}
|
||||
$('#excelTable tbody').off('click', '.importRow').on('click', '.importRow', async function () {
|
||||
const $row = $(this).closest('tr');
|
||||
const rowData = dataTable.row($row).data();
|
||||
if (!rowData) return;
|
||||
|
||||
document.getElementById('importBtn').addEventListener('click', function () {
|
||||
const selectedRows = [];
|
||||
const fila = rowData.slice(1, 6); // solo datos de negocio
|
||||
|
||||
dataTable.rows().every(function () {
|
||||
const data = this.data();
|
||||
const checkboxHtml = $(data[0]).find('input.select-row');
|
||||
if (checkboxHtml.length > 0 && checkboxHtml.is(':checked') && !checkboxHtml.is(':disabled')) {
|
||||
selectedRows.push(data.slice(1, -1)); // sin checkbox ni botones
|
||||
try {
|
||||
const response = await fetch('/importador/catalogo/importar-fila', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '<?= csrf_hash() ?>'
|
||||
},
|
||||
body: JSON.stringify({ fila: fila })
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result.status === 200) {
|
||||
const skUrl = result.data?.sk_url ?? null;
|
||||
|
||||
// Actualizar campo "Notas" con el enlace
|
||||
if (skUrl) {
|
||||
const notasHtml = `<a href="${skUrl}" target="_blank" class="btn btn-sm btn-secondary">Ver presupuesto</a>`;
|
||||
// La columna de notas es la posición 6 (índice 6)
|
||||
rowData[6] = notasHtml;
|
||||
dataTable.row($row).data(rowData).draw(false); // Redibujar la fila SIN perder scroll ni filtros
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
title: 'Importado correctamente',
|
||||
html: skUrl
|
||||
? `La fila se importó exitosamente.<br><br><a href="${skUrl}" target="_blank" class="btn btn-primary mt-2">Ver presupuesto</a>`
|
||||
: 'La fila se importó exitosamente.',
|
||||
icon: 'success',
|
||||
confirmButtonText: 'Aceptar',
|
||||
buttonsStyling: true,
|
||||
customClass: { confirmButton: 'btn btn-success' }
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error',
|
||||
text: result.message ?? 'Hubo un error al importar esta fila.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'Aceptar',
|
||||
buttonsStyling: true,
|
||||
customClass: { confirmButton: 'btn btn-danger' }
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error en la llamada a importar-fila:', error);
|
||||
Swal.fire({
|
||||
title: 'Error',
|
||||
text: 'Error de comunicación con el servidor.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'Aceptar',
|
||||
buttonsStyling: true,
|
||||
customClass: { confirmButton: 'btn btn-danger' }
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (selectedRows.length === 0) {
|
||||
|
||||
// Select All funcional
|
||||
$('#selectAll').off('change').on('change', function () {
|
||||
const checked = $(this).is(':checked');
|
||||
$('#excelTable tbody input.select-row:enabled').prop('checked', checked);
|
||||
});
|
||||
}
|
||||
|
||||
/* Importacion */
|
||||
document.getElementById('importBtn').addEventListener('click', function () {
|
||||
const filasAptas = [];
|
||||
|
||||
dataTable.rows().every(function () {
|
||||
const rowNode = this.node();
|
||||
const checkbox = $(rowNode).find('input.select-row');
|
||||
|
||||
if (checkbox.length > 0 && checkbox.is(':checked') && !checkbox.is(':disabled')) {
|
||||
const rowData = this.data();
|
||||
filasAptas.push({ fila: rowData.slice(1, 6), rowNode: rowNode, rowData: rowData });
|
||||
}
|
||||
});
|
||||
|
||||
if (filasAptas.length === 0) {
|
||||
Swal.fire({
|
||||
title: 'Atención',
|
||||
text: 'No hay filas aptas seleccionadas para importar.',
|
||||
@ -157,35 +236,66 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/importar', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '<?= csrf_hash() ?>'
|
||||
},
|
||||
body: JSON.stringify({ data: selectedRows })
|
||||
}).then(res => res.json())
|
||||
.then(response => {
|
||||
Swal.fire({
|
||||
title: 'Importación exitosa',
|
||||
text: response.message,
|
||||
icon: 'success',
|
||||
confirmButtonText: 'Aceptar',
|
||||
buttonsStyling: true,
|
||||
customClass: { confirmButton: 'btn btn-success' }
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
Swal.fire({
|
||||
title: 'Error',
|
||||
text: 'Error importando datos.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'Aceptar',
|
||||
buttonsStyling: true,
|
||||
customClass: { confirmButton: 'btn btn-danger' }
|
||||
});
|
||||
Swal.fire({
|
||||
title: '¿Confirmar importación?',
|
||||
text: `Se van a importar ${filasAptas.length} filas.`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Sí, importar',
|
||||
cancelButtonText: 'Cancelar',
|
||||
reverseButtons: true,
|
||||
buttonsStyling: true,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary',
|
||||
cancelButton: 'btn btn-secondary'
|
||||
}
|
||||
}).then(async (result) => {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
for (const fila of filasAptas) {
|
||||
try {
|
||||
const response = await fetch('/importador/catalogo/importar-fila', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '<?= csrf_hash() ?>'
|
||||
},
|
||||
body: JSON.stringify({ fila: fila.fila })
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result.status === 200) {
|
||||
const skUrl = result.data?.sk_url ?? null;
|
||||
|
||||
if (skUrl) {
|
||||
fila.rowData[6] = `<a href="${skUrl}" target="_blank" class="btn btn-sm btn-primary">Ver presupuesto</a>`;
|
||||
} else {
|
||||
fila.rowData[6] = `<span class="badge bg-success">Importado</span>`;
|
||||
}
|
||||
} else {
|
||||
fila.rowData[6] = `<span class="badge bg-danger">${result.message ?? 'Error desconocido'}</span>`;
|
||||
}
|
||||
|
||||
dataTable.row(fila.rowNode).data(fila.rowData).draw(false);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error importando fila:', error);
|
||||
fila.rowData[6] = `<span class="badge bg-danger">Error de comunicación</span>`;
|
||||
dataTable.row(fila.rowNode).data(fila.rowData).draw(false);
|
||||
}
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
title: 'Importación finalizada',
|
||||
text: 'Se han procesado todas las filas seleccionadas.',
|
||||
icon: 'success',
|
||||
confirmButtonText: 'Aceptar',
|
||||
buttonsStyling: true,
|
||||
customClass: { confirmButton: 'btn btn-success' }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user