diff --git a/ci4/app/Config/RBAC.zip b/ci4/app/Config/RBAC.zip deleted file mode 100644 index 7c497e79..00000000 Binary files a/ci4/app/Config/RBAC.zip and /dev/null differ diff --git a/ci4/app/Config/Routes/ImportadoresRoutes.php b/ci4/app/Config/Routes/ImportadoresRoutes.php new file mode 100644 index 00000000..df3ffa12 --- /dev/null +++ b/ci4/app/Config/Routes/ImportadoresRoutes.php @@ -0,0 +1,24 @@ +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'); + + + }); +}); \ No newline at end of file diff --git a/ci4/app/Controllers/Catalogo/notas.txt b/ci4/app/Controllers/Catalogo/notas.txt deleted file mode 100644 index 3d18002e..00000000 --- a/ci4/app/Controllers/Catalogo/notas.txt +++ /dev/null @@ -1,2 +0,0 @@ -Portada Id Cliente Título Edición Autor Archivo ISBN EAN Páginas Acciones -Lo que hay que listar \ No newline at end of file diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php new file mode 100644 index 00000000..7c82e02a --- /dev/null +++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php @@ -0,0 +1,237 @@ +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' + ]); + } + +} diff --git a/ci4/app/Database/Migrations/2025-04-22-204851_CreateCatalogoLibros.php b/ci4/app/Database/Migrations/2025-04-22-204851_CreateCatalogoLibros.php index dc69047d..3c32a7a7 100644 --- a/ci4/app/Database/Migrations/2025-04-22-204851_CreateCatalogoLibros.php +++ b/ci4/app/Database/Migrations/2025-04-22-204851_CreateCatalogoLibros.php @@ -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); diff --git a/ci4/app/Language/en/App.php b/ci4/app/Language/en/App.php index 649f02b6..633d7f4f 100755 --- a/ci4/app/Language/en/App.php +++ b/ci4/app/Language/en/App.php @@ -700,7 +700,7 @@ return [ "menu_digitalizacion" => "Digitalisation", - "menu_importacion" => "Import", + "menu_importadores" => "Import", "menu_catalogo" => "Catalogue", "menu_catalogo_libros" => "Books", diff --git a/ci4/app/Language/es/App.php b/ci4/app/Language/es/App.php index 1a56b5fa..a65094ca 100755 --- a/ci4/app/Language/es/App.php +++ b/ci4/app/Language/es/App.php @@ -720,7 +720,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", diff --git a/ci4/app/Language/es/Importador.php b/ci4/app/Language/es/Importador.php new file mode 100644 index 00000000..8d4d36dd --- /dev/null +++ b/ci4/app/Language/es/Importador.php @@ -0,0 +1,80 @@ + '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:', +]; diff --git a/ci4/app/Language/es/RolesPermisos.php b/ci4/app/Language/es/RolesPermisos.php index 0bcc7616..ce946f1e 100755 --- a/ci4/app/Language/es/RolesPermisos.php +++ b/ci4/app/Language/es/RolesPermisos.php @@ -67,6 +67,11 @@ return [ 'vencimientosPermission' => 'Vencimientos', "ticketsSection" => "Tickets", 'produccionSection' => 'Producción', + 'catalogoSection' => 'Catálogo', + 'importadoresSection' => 'Importadores', + 'catalogoPermission' => 'Desde catálogo', + + 'validation' => [ 'id' => [ diff --git a/ci4/app/Views/themes/vuexy/form/importador/.delete b/ci4/app/Views/themes/vuexy/form/importador/.delete new file mode 100644 index 00000000..e69de29b diff --git a/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php b/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php new file mode 100644 index 00000000..a7b2e8dc --- /dev/null +++ b/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php @@ -0,0 +1,113 @@ +include('themes/_commonPartialsBs/datatables') ?> +include('themes/_commonPartialsBs/sweetalert') ?> +extend('themes/vuexy/main/defaultlayout') ?> + +section('content'); ?> +
+
+ +
+
+

+
+ +
+ + + +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ + +endSection() ?> + + + +section('css') ?> +"> + +endSection() ?> + + +section('additionalExternalJs') ?> + + + + + + + + + + +endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/main/menu_impresion.php b/ci4/app/Views/themes/vuexy/main/menu_impresion.php index 64464e5c..97d53883 100755 --- a/ci4/app/Views/themes/vuexy/main/menu_impresion.php +++ b/ci4/app/Views/themes/vuexy/main/menu_impresion.php @@ -32,7 +32,7 @@ require "menus/maquinista_menu.php"; - require "menus/importacion_menu.php"; + require "menus/importadores_menu.php"; require "menus/catalogo_menu.php"; diff --git a/ci4/app/Views/themes/vuexy/main/menus/importacion_menu.php b/ci4/app/Views/themes/vuexy/main/menus/importacion_menu.php deleted file mode 100755 index f3d1a48b..00000000 --- a/ci4/app/Views/themes/vuexy/main/menus/importacion_menu.php +++ /dev/null @@ -1,15 +0,0 @@ -user()->inGroup('beta')) { -?> - - - \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/main/menus/importadores_menu.php b/ci4/app/Views/themes/vuexy/main/menus/importadores_menu.php new file mode 100644 index 00000000..8abad150 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/main/menus/importadores_menu.php @@ -0,0 +1,27 @@ +user()->can('importadores.menu')) { + ?> + + + + + \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/pages/importadores/.delete b/httpdocs/assets/js/safekat/pages/importadores/.delete new file mode 100644 index 00000000..e69de29b diff --git a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js new file mode 100644 index 00000000..8fce7010 --- /dev/null +++ b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js @@ -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 = ``; + + actionBtnsHtml = ` +
+ + +
+ `; + } else { + checkboxHtml = ``; + + actionBtnsHtml = ` +
+ No Apto + +
+ `; + } + + 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': '' + }, + 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': '' + }, + 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' } + }); + }); + }); + +});