mirror of
https://git.imnavajas.es/jjimenez/safekat.git
synced 2025-07-25 22:52:08 +00:00
Merge branch 'feat/importador_rama' into 'main'
Feat/importador rama See merge request jjimenez/safekat!750
This commit is contained in:
Binary file not shown.
24
ci4/app/Config/Routes/ImportadoresRoutes.php
Normal file
24
ci4/app/Config/Routes/ImportadoresRoutes.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use CodeIgniter\Router\RouteCollection;
|
||||
|
||||
/** @var RouteCollection $routes */
|
||||
|
||||
/* Rutas para tarifas */
|
||||
$routes->group('importador', ['namespace' => 'App\Controllers\Importadores'], function ($routes) {
|
||||
/* Libros */
|
||||
$routes->group('catalogo', ['namespace' => 'App\Controllers\Importadores'], function ($routes) {
|
||||
/**======================
|
||||
* Tool
|
||||
*========================**/
|
||||
$routes->get('', 'ImportadorCatalogo::index', ['as' => 'importadorCatalogoTool']);
|
||||
|
||||
|
||||
/**======================
|
||||
* AJAX
|
||||
*========================**/
|
||||
$routes->post('validar-fila', 'ImportadorCatalogo::validarFila');
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
@ -1,2 +0,0 @@
|
||||
Portada Id Cliente Título Edición Autor Archivo ISBN EAN Páginas Acciones
|
||||
Lo que hay que listar
|
||||
237
ci4/app/Controllers/Importadores/ImportadorCatalogo.php
Normal file
237
ci4/app/Controllers/Importadores/ImportadorCatalogo.php
Normal file
@ -0,0 +1,237 @@
|
||||
<?php
|
||||
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;
|
||||
|
||||
class ImportadorCatalogo extends BaseResourceController
|
||||
{
|
||||
|
||||
protected $modelName = CatalogoLibroModel::class;
|
||||
protected $format = 'json';
|
||||
|
||||
protected static $singularObjectName = 'Importador';
|
||||
protected static $singularObjectNameCc = 'ImportadorCatalogo';
|
||||
protected static $pluralObjectName = 'Importadores';
|
||||
protected static $pluralObjectNameCc = 'importadores';
|
||||
|
||||
protected static $controllerSlug = 'importador';
|
||||
|
||||
protected static $viewPath = 'themes/vuexy/form/importador/catalogo/';
|
||||
|
||||
protected $indexRoute = 'ImportadorCatalogoTool';
|
||||
|
||||
|
||||
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
|
||||
{
|
||||
$this->viewData['pageTitle'] = lang('Importador.listingPage');
|
||||
$this->viewData['usingSweetAlert'] = true;
|
||||
|
||||
// Breadcrumbs (IMN)
|
||||
$this->viewData['breadcrumb'] = [
|
||||
['title' => lang("App.menu_importadores"), 'route' => "javascript:void(0);", 'active' => false],
|
||||
['title' => lang("App.menu_importadores_catalogo"), 'route' => route_to('importadorCatalogoTool'), 'active' => true]
|
||||
];
|
||||
|
||||
parent::initController($request, $response, $logger);
|
||||
}
|
||||
|
||||
|
||||
public function index()
|
||||
{
|
||||
|
||||
$viewData = [
|
||||
'currentModule' => static::$controllerSlug,
|
||||
'pageSubTitle' => lang('Basic.global.ManageAllRecords', [lang('Importador.importadorCatalogoTitle')]),
|
||||
'catalogoLibrosEntity' => new CatalogoLibroEntity(),
|
||||
'usingServerSideDataTable' => true,
|
||||
|
||||
];
|
||||
|
||||
$viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class
|
||||
|
||||
return view(static::$viewPath . 'viewImportadorCatalogoTool', $viewData);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
||||
if (!$json || !isset($json->fila[0])) {
|
||||
return $this->response->setJSON([
|
||||
'apto' => false,
|
||||
'reason' => 'Datos inválidos'
|
||||
]);
|
||||
}
|
||||
|
||||
$input = trim($json->fila[0]); // Asumimos que 'input' es el primer campo de la fila
|
||||
|
||||
if (empty($input)) {
|
||||
return $this->response->setJSON([
|
||||
'apto' => false,
|
||||
'reason' => 'ISBN no proporiconado'
|
||||
]);
|
||||
}
|
||||
|
||||
$catalogoModel = new CatalogoLibroModel();
|
||||
|
||||
// 1. Buscar por ISBN exacto
|
||||
$libroPorIsbn = $catalogoModel->where('isbn', $input)->first();
|
||||
|
||||
if ($libroPorIsbn) {
|
||||
return $this->response->setJSON([
|
||||
'apto' => true
|
||||
]);
|
||||
}
|
||||
|
||||
// 2. Buscar por EAN sin guiones
|
||||
$eanLimpio = str_replace('-', '', $input);
|
||||
|
||||
$libroPorEan = $catalogoModel->where('REPLACE(ean, "-", "")', $eanLimpio)->first();
|
||||
|
||||
if ($libroPorEan) {
|
||||
return $this->response->setJSON([
|
||||
'apto' => true
|
||||
]);
|
||||
}
|
||||
|
||||
// No encontrado
|
||||
return $this->response->setJSON([
|
||||
'apto' => false,
|
||||
'reason' => 'No encontrado en catálogo'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,69 +11,78 @@ class CreateCatalogoLibros extends Migration
|
||||
$this->db->query('SET foreign_key_checks = 0');
|
||||
|
||||
$this->forge->addField([
|
||||
'id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'auto_increment' => true],
|
||||
'cliente_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'proveedor_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'user_created_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'default' => 1],
|
||||
'user_update_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'default' => 1],
|
||||
'cubierta_archivo' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'cubierta_url' => ['type' => 'VARCHAR', 'constraint' => 500, 'null' => true],
|
||||
'ancho' => ['type' => 'DOUBLE', 'constraint' => '8,2'],
|
||||
'alto' => ['type' => 'DOUBLE', 'constraint' => '8,2'],
|
||||
'peso' => ['type' => 'DOUBLE', 'constraint' => '8,2', 'null' => true],
|
||||
'titulo' => ['type' => 'VARCHAR', 'constraint' => 300],
|
||||
'autor' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'autor_entidad' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'traductor' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'ilustrador' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'idioma' => ['type' => 'VARCHAR', 'constraint' => 3, 'default' => 'spa'],
|
||||
'num_edic' => ['type' => 'INT', 'default' => 1, 'null' => true],
|
||||
'fecha_disponibilidad' => ['type' => 'DATE', 'null' => true],
|
||||
'fecha_public' => ['type' => 'DATE', 'null' => true],
|
||||
'num_fotos' => ['type' => 'INT', 'default' => 0],
|
||||
'num_ilustr' => ['type' => 'INT', 'default' => 0],
|
||||
'num_ilustr_color' => ['type' => 'INT', 'default' => 0],
|
||||
'num_ilustr_bn' => ['type' => 'INT', 'default' => 0],
|
||||
'coleccion' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'isk' => ['type' => 'VARCHAR', 'constraint' => 64, 'null' => true],
|
||||
'isbn' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'ean' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'editorial' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'resumen' => ['type' => 'TEXT', 'null' => true],
|
||||
'resumen_breve' => ['type' => 'TEXT', 'null' => true],
|
||||
'sello' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'paginas' => ['type' => 'INT'],
|
||||
'tipo_impresion' => ['type' => 'ENUM', 'constraint' => ['negro','negrohq','color','colorhq'], 'null' => true],
|
||||
'comentarios' => ['type' => 'TEXT', 'null' => true],
|
||||
'negro_paginas' => ['type' => 'INT', 'null' => true],
|
||||
'negro_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'negro_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'negro_pod_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'negro_pod_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'color_paginas' => ['type' => 'INT', 'null' => true],
|
||||
'color_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'color_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'color_pod_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'color_pod_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'cubierta_paginas' => ['type' => 'INT', 'null' => true],
|
||||
'cubierta_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'cubierta_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'cubierta_acabado_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'cubierta_ancho_solapas' => ['type' => 'DOUBLE', 'constraint' => '8,2', 'default' => 0.00, 'unsigned' => true],
|
||||
'cubierta_pod_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'cubierta_pod_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'sobrecubierta_paginas' => ['type' => 'INT', 'null' => true],
|
||||
'sobrecubierta_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'sobrecubierta_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'auto_increment' => true],
|
||||
'cliente_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'proveedor_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'user_created_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'default' => 1],
|
||||
'user_update_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'default' => 1],
|
||||
'cubierta_archivo' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'cubierta_url' => ['type' => 'VARCHAR', 'constraint' => 500, 'null' => true],
|
||||
'ancho' => ['type' => 'DOUBLE', 'constraint' => '8,2'],
|
||||
'alto' => ['type' => 'DOUBLE', 'constraint' => '8,2'],
|
||||
'peso' => ['type' => 'DOUBLE', 'constraint' => '8,2', 'null' => true],
|
||||
'titulo' => ['type' => 'VARCHAR', 'constraint' => 300],
|
||||
'autor' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'autor_entidad' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'traductor' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'ilustrador' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'idioma' => ['type' => 'VARCHAR', 'constraint' => 3, 'default' => 'spa'],
|
||||
'num_edic' => ['type' => 'INT', 'default' => 1, 'null' => true],
|
||||
'fecha_disponibilidad' => ['type' => 'DATE', 'null' => true],
|
||||
'fecha_public' => ['type' => 'DATE', 'null' => true],
|
||||
'num_fotos' => ['type' => 'INT', 'default' => 0],
|
||||
'num_ilustr' => ['type' => 'INT', 'default' => 0],
|
||||
'num_ilustr_color' => ['type' => 'INT', 'default' => 0],
|
||||
'num_ilustr_bn' => ['type' => 'INT', 'default' => 0],
|
||||
'coleccion' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'isk' => ['type' => 'VARCHAR', 'constraint' => 64, 'null' => true],
|
||||
'isbn' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'ean' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'editorial' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'resumen' => ['type' => 'TEXT', 'null' => true],
|
||||
'resumen_breve' => ['type' => 'TEXT', 'null' => true],
|
||||
'sello' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'paginas' => ['type' => 'INT'],
|
||||
'tipo_impresion' => ['type' => 'ENUM', 'constraint' => ['negro', 'negrohq', 'color', 'colorhq'], 'null' => true],
|
||||
'comentarios' => ['type' => 'TEXT', 'null' => true],
|
||||
'negro_paginas' => ['type' => 'INT', 'null' => true],
|
||||
'negro_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'negro_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'negro_pod_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'negro_pod_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'color_paginas' => ['type' => 'INT', 'null' => true],
|
||||
'color_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'color_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'color_pod_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'color_pod_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'cubierta_paginas' => ['type' => 'INT', 'null' => true],
|
||||
'cubierta_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'cubierta_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'cubierta_acabado_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'cubierta_ancho_solapas' => ['type' => 'DOUBLE', 'constraint' => '8,2', 'default' => 0.00, 'unsigned' => true],
|
||||
'cubierta_pod_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'cubierta_pod_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'sobrecubierta_paginas' => ['type' => 'INT', 'null' => true],
|
||||
'sobrecubierta_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'sobrecubierta_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'sobrecubierta_acabado_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'sobrecubierta_ancho_solapas' => ['type' => 'DOUBLE', 'constraint' => '8,2', 'default' => 0.00, 'unsigned' => true],
|
||||
'sobrecubierta_pod_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'sobrecubierta_pod_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'encuadernacion_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'ubicacion' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'created_at' => ['type' => 'TIMESTAMP', 'default' => 'CURRENT_TIMESTAMP'],
|
||||
'updated_at' => ['type' => 'TIMESTAMP', 'null' => true],
|
||||
'deleted_at' => ['type' => 'TIMESTAMP', 'null' => true],
|
||||
'sobrecubierta_pod_papel_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'sobrecubierta_pod_gramaje' => ['type' => 'DOUBLE', 'null' => true],
|
||||
'encuadernacion_id' => ['type' => 'INT', 'constraint' => 10, 'unsigned' => true, 'null' => true],
|
||||
'ubicacion' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||
'created_at' => [
|
||||
'type' => 'TIMESTAMP',
|
||||
'default' => new \CodeIgniter\Database\RawSql('CURRENT_TIMESTAMP'),
|
||||
],
|
||||
'updated_at' => [
|
||||
'type' => 'TIMESTAMP',
|
||||
'null' => true,
|
||||
],
|
||||
'deleted_at' => [
|
||||
'type' => 'TIMESTAMP',
|
||||
'null' => true,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->forge->addKey('id', true);
|
||||
|
||||
@ -699,7 +699,7 @@ return [
|
||||
|
||||
"menu_digitalizacion" => "Digitalisation",
|
||||
|
||||
"menu_importacion" => "Import",
|
||||
"menu_importadores" => "Import",
|
||||
|
||||
"menu_catalogo" => "Catalogue",
|
||||
"menu_catalogo_libros" => "Books",
|
||||
|
||||
@ -719,7 +719,8 @@ return [
|
||||
|
||||
"menu_digitalizacion" => "Digitalización",
|
||||
|
||||
"menu_importacion" => "Importación",
|
||||
"menu_importadores" => "Importadores",
|
||||
"menu_importadores_catalogo" => "Desde catálogo",
|
||||
|
||||
"menu_catalogo" => "Catálogo",
|
||||
"menu_catalogo_libros" => "Libros",
|
||||
|
||||
80
ci4/app/Language/es/Importador.php
Normal file
80
ci4/app/Language/es/Importador.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'moduleTitle' => 'Importadores',
|
||||
'importadorCatalogoTitle' => 'Importador RA-MA Ediciones S.L.',
|
||||
'catalogo' => 'catálogo',
|
||||
'input' => 'ISBN',
|
||||
'descripcion' => 'Título',
|
||||
'idlinea' => 'Ref. cliente',
|
||||
'cnt_pedida' => 'Unidades',
|
||||
'precio_compra' => 'Precio Compra',
|
||||
'importar' => 'Importar',
|
||||
'subirArchivo' => 'Cargar Excel proporcionado por RA-MA',
|
||||
|
||||
'libro' => 'libro',
|
||||
'id' => 'ID',
|
||||
'clienteId' => 'Cliente',
|
||||
'cliente' => 'Cliente',
|
||||
'userCreatedId' => 'Usuario Creador',
|
||||
'userUpdateId' => 'Usuario Actualizador',
|
||||
'portada' => 'Portada',
|
||||
'ancho' => 'Ancho',
|
||||
'alto' => 'Alto',
|
||||
'peso' => 'Peso',
|
||||
'titulo' => 'Título',
|
||||
'autor' => 'Autor',
|
||||
'autorEntidad' => 'Entidad del Autor',
|
||||
'traductor' => 'Traductor',
|
||||
'ilustrador' => 'Ilustrador',
|
||||
'idioma' => 'Idioma',
|
||||
'numEdic' => 'Número de Edición',
|
||||
'edicion' => 'Edición',
|
||||
'fechaDisponibilidad' => 'Fecha de Disponibilidad',
|
||||
'fechaPublic' => 'Fecha de Publicación',
|
||||
'numFotos' => 'Número de Fotos',
|
||||
'numIlustr' => 'Número de Ilustraciones',
|
||||
'numIlustrColor' => 'Ilustraciones a Color',
|
||||
'numIlustrBn' => 'Ilustraciones en Blanco y Negro',
|
||||
'coleccion' => 'Colección',
|
||||
'isbn' => 'ISBN',
|
||||
'ean' => 'EAN',
|
||||
'editorial' => 'Editorial',
|
||||
'resumen' => 'Resumen',
|
||||
'resumenBreve' => 'Resumen Breve',
|
||||
'sello' => 'Sello',
|
||||
'paginas' => 'Páginas',
|
||||
'tipoImpresion' => 'Tipo de Impresión',
|
||||
'seleccionarTipoImpresion' => 'Seleccionar tipo de impresión',
|
||||
'solapasAncho' => 'Ancho de Solapas',
|
||||
'cubiertasAncho' => 'Ancho de Cubiertas',
|
||||
'comentarios' => 'Comentarios',
|
||||
'negroPaginas' => 'Páginas Negras',
|
||||
'negroPapel' => 'Papel Negro',
|
||||
'negroGramaje' => 'Gramaje Negro',
|
||||
'colorPaginas' => 'Páginas a Color',
|
||||
'colorPapel' => 'Papel a Color',
|
||||
'colorGramaje' => 'Gramaje Color',
|
||||
'portadaPaginas' => 'Páginas de Portada',
|
||||
'portadaPapel' => 'Papel de Portada',
|
||||
'portadaGramaje' => 'Gramaje Portada',
|
||||
'portadaAcabado' => 'Acabado Portada',
|
||||
'cubiertaPaginas' => 'Páginas de Cubierta',
|
||||
'cubiertaPapel' => 'Papel de Cubierta',
|
||||
'cubiertaGramaje' => 'Gramaje Cubierta',
|
||||
'cubiertaAcabado' => 'Acabado Cubierta',
|
||||
'encuardenacion' => 'Encuadernación',
|
||||
'ubicacion' => 'Ubicación',
|
||||
'createdAt' => 'Fecha de Creación',
|
||||
'updatedAt' => 'Fecha de Actualización',
|
||||
'deletedAt' => 'Fecha de Eliminación',
|
||||
|
||||
'catalogoLibro' => 'Libro',
|
||||
'catalogoLibroList' => 'Lista de Libros',
|
||||
'datosGenerales' => 'Datos generales del libro',
|
||||
'otrosDatosLibro' => 'Otros datos del libro',
|
||||
'configuracionLibro' => 'Configuración del libro',
|
||||
'ficherosLibro' => 'Ficheros',
|
||||
'created_by_at' => 'Creado:',
|
||||
'updated_by_at' => 'Actualizado:',
|
||||
];
|
||||
@ -67,6 +67,11 @@ return [
|
||||
'vencimientosPermission' => 'Vencimientos',
|
||||
"ticketsSection" => "Tickets",
|
||||
'produccionSection' => 'Producción',
|
||||
'catalogoSection' => 'Catálogo',
|
||||
'importadoresSection' => 'Importadores',
|
||||
'catalogoPermission' => 'Desde catálogo',
|
||||
|
||||
|
||||
|
||||
'validation' => [
|
||||
'id' => [
|
||||
|
||||
0
ci4/app/Views/themes/vuexy/form/importador/.delete
Normal file
0
ci4/app/Views/themes/vuexy/form/importador/.delete
Normal file
@ -0,0 +1,113 @@
|
||||
<?= $this->include('themes/_commonPartialsBs/datatables') ?>
|
||||
<?= $this->include('themes/_commonPartialsBs/sweetalert') ?>
|
||||
<?= $this->extend('themes/vuexy/main/defaultlayout') ?>
|
||||
|
||||
<?= $this->section('content'); ?>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><?= lang('Importador.importadorCatalogoTitle') ?></h3>
|
||||
</div><!--//.card-header -->
|
||||
|
||||
<form id="catalogoLibroForm" class="card-body" method="post" action="#">
|
||||
<?= csrf_field() ?>
|
||||
|
||||
<!-- card-body -->
|
||||
<div class="card-body">
|
||||
|
||||
<?= view('themes/_commonPartialsBs/_alertBoxes'); ?>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="excelFile"
|
||||
class="form-label"><?= lang('Importador.subirArchivo') ?? 'Subir archivo Excel' ?></label>
|
||||
<input type="file" class="form-control" id="excelFile" name="excelFile"
|
||||
accept=".xlsx, .xls">
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 mb-3 d-flex align-items-end">
|
||||
<button type="button" id="importBtn" class="btn btn-success w-100">
|
||||
<i class="fas fa-file-import me-2"></i> <?= lang('Importador.importar') ?? 'Importar' ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div><!--//.card-body -->
|
||||
<div class="card-footer">
|
||||
|
||||
</div><!--//.card-footer -->
|
||||
</div><!--//.card -->
|
||||
</div><!--//.col -->
|
||||
</div><!--//.row -->
|
||||
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
|
||||
|
||||
<?= $this->section('css') ?>
|
||||
<link rel="stylesheet"
|
||||
href="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/buttons.bootstrap5.min.css") ?>">
|
||||
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.css') ?>" />
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
|
||||
<?= $this->section('additionalExternalJs') ?>
|
||||
<script
|
||||
src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/dataTables.buttons.min.js") ?>"></script>
|
||||
<script
|
||||
src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/buttons.bootstrap5.min.js") ?>"></script>
|
||||
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/buttons.html5.min.js") ?>"></script>
|
||||
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/buttons.print.min.js") ?>"></script>
|
||||
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/jszip/jszip.min.js") ?>"></script>
|
||||
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/pdfmake/pdfmake.min.js") ?>"
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/pdfmake/vfs_fonts.js") ?>"></script>
|
||||
<script src="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.js') ?>"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
<script type="module" src="<?= site_url("assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js") ?>"></script>
|
||||
<?= $this->endSection() ?>
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
require "menus/maquinista_menu.php";
|
||||
|
||||
require "menus/importacion_menu.php";
|
||||
require "menus/importadores_menu.php";
|
||||
|
||||
require "menus/catalogo_menu.php";
|
||||
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MENU IMPORTACION
|
||||
*/
|
||||
if (auth()->user()->inGroup('beta')) {
|
||||
?>
|
||||
<!-- Import -->
|
||||
<li class="menu-item">
|
||||
<a href="<?= site_url("importacion/importar") ?>" class="menu-link beta">
|
||||
<i class="menu-icon tf-icons ti ti-file-import"></i>
|
||||
<div> <?= lang("App.menu_importacion") ?></div>
|
||||
</a>
|
||||
</li>
|
||||
<?php } ?>
|
||||
27
ci4/app/Views/themes/vuexy/main/menus/importadores_menu.php
Normal file
27
ci4/app/Views/themes/vuexy/main/menus/importadores_menu.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MENU IMPORTACION
|
||||
*/
|
||||
if (auth()->user()->can('importadores.menu')) {
|
||||
?>
|
||||
|
||||
<!-- Importadores -->
|
||||
<li class="menu-item">
|
||||
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||
<i class="menu-icon tf-icons ti ti-file-import"></i>
|
||||
<div><?= lang("App.menu_importadores") ?> </div>
|
||||
</a>
|
||||
<ul class="menu-sub">
|
||||
<?php if (auth()->user()->can('importadores.catalogo')) { ?>
|
||||
<li class="menu-item">
|
||||
<a href="<?= route_to("importadorCatalogoTool") ?>" class="menu-link">
|
||||
<?= lang("App.menu_importadores_catalogo") ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
@ -0,0 +1,191 @@
|
||||
import Ajax from '../../../components/ajax.js';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
const TABLE_COLUMNS = ["input", "idlinea", "descripcion", "cnt_pedida", "precio_compra"];
|
||||
let dataTable;
|
||||
|
||||
dataTable = $('#excelTable').DataTable({
|
||||
orderCellsTop: true,
|
||||
responsive: true,
|
||||
scrollX: true,
|
||||
lengthMenu: [5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500],
|
||||
pageLength: 25,
|
||||
lengthChange: true,
|
||||
dom: 'lfrtip',
|
||||
language: {
|
||||
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
|
||||
},
|
||||
order: [[1, 'asc']]
|
||||
});
|
||||
|
||||
document.getElementById('excelFile').addEventListener('change', function (e) {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
const data = new Uint8Array(e.target.result);
|
||||
const workbook = XLSX.read(data, { type: 'array' });
|
||||
|
||||
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||
const jsonData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
|
||||
|
||||
validateAndLoadDataTable(jsonData);
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
|
||||
async function validateAndLoadDataTable(data) {
|
||||
if (data.length === 0) return;
|
||||
|
||||
const headers = data[0].map(h => h.toString().trim());
|
||||
const headerMap = {};
|
||||
headers.forEach((name, idx) => {
|
||||
headerMap[name.toLowerCase()] = idx;
|
||||
});
|
||||
|
||||
const missing = TABLE_COLUMNS.filter(col => !(col in headerMap));
|
||||
if (missing.length > 0) {
|
||||
Swal.fire({
|
||||
title: 'Error',
|
||||
text: 'Faltan las siguientes columnas: ' + missing.join(', '),
|
||||
icon: 'error',
|
||||
confirmButtonText: 'Aceptar',
|
||||
buttonsStyling: true,
|
||||
customClass: { confirmButton: 'btn btn-danger' }
|
||||
});
|
||||
dataTable.clear().draw();
|
||||
return;
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
for (let i = 1; i < data.length; i++) {
|
||||
const rowData = TABLE_COLUMNS.map(col => data[i][headerMap[col]] ?? '');
|
||||
|
||||
// Llamar backend para validar la fila
|
||||
const isValid = await validarFila(rowData);
|
||||
|
||||
let checkboxHtml = '';
|
||||
let actionBtnsHtml = '';
|
||||
|
||||
if (isValid) {
|
||||
checkboxHtml = `<input type="checkbox" class="select-row form-check-input" checked>`;
|
||||
|
||||
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>
|
||||
`;
|
||||
} else {
|
||||
checkboxHtml = `<input type="checkbox" class="select-row form-check-input" disabled>`;
|
||||
|
||||
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>
|
||||
`;
|
||||
}
|
||||
|
||||
rows.push([checkboxHtml, ...rowData, actionBtnsHtml]);
|
||||
}
|
||||
|
||||
dataTable.clear().rows.add(rows).draw();
|
||||
|
||||
setupEventListeners();
|
||||
}
|
||||
|
||||
async function validarFila(rowData) {
|
||||
try {
|
||||
const response = await fetch('/importador/catalogo/validar-fila', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '<?= csrf_hash() ?>'
|
||||
},
|
||||
body: JSON.stringify({ fila: rowData })
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
return result.apto === true;
|
||||
} catch (error) {
|
||||
console.error('Error validando fila', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
$('#excelTable tbody').off('click', '.deleteRow').on('click', '.deleteRow', 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
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('importBtn').addEventListener('click', function () {
|
||||
const selectedRows = [];
|
||||
|
||||
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
|
||||
}
|
||||
});
|
||||
|
||||
if (selectedRows.length === 0) {
|
||||
Swal.fire({
|
||||
title: 'Atención',
|
||||
text: 'No hay filas aptas seleccionadas para importar.',
|
||||
icon: 'warning',
|
||||
confirmButtonText: 'Aceptar',
|
||||
buttonsStyling: true,
|
||||
customClass: { confirmButton: 'btn btn-warning' }
|
||||
});
|
||||
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' }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user