44 Commits

Author SHA1 Message Date
36c9227586 fix pdf tables encuadernacion. Add tarifa acabado configuration for ots 2025-04-30 01:25:24 +02:00
96a6845c0c Merge branch 'feat/importador_rama_2' into 'main'
Feat/importador rama 2

See merge request jjimenez/safekat!754
2025-04-29 15:10:55 +00:00
eed5c0994e Importador rama con ajuste del precio 2025-04-29 17:09:19 +02:00
e2ab42cd84 Arreglado bug impresora de tickets (logistica) 2025-04-29 17:01:16 +02:00
7da76af866 Primera version del importador RAMA 2025-04-29 15:42:50 +02:00
bf1e66d746 Corregido bug en API imprimelibros 2025-04-29 12:40:35 +02:00
adccc414be Merge branch 'fix/bugs-ot' into 'main'
Fix/bugs ot

See merge request jjimenez/safekat!752
2025-04-28 06:13:50 +00:00
95fa192cb9 remove ? from orden_trabajo pdf 2025-04-28 08:12:22 +02:00
9310d2dabd delete class text-center from div.card otTask 2025-04-28 08:06:44 +02:00
3abf45ca6e tiempo real tarea empty when created 2025-04-28 08:00:39 +02:00
6ea22066c2 Merge branch 'feat/festivos-calendar' into 'main'
Feat/festivos calendar

See merge request jjimenez/safekat!751
2025-04-28 00:11:16 +00:00
bf21a336b1 Merge branch 'main' into feat/festivos-calendar 2025-04-28 02:10:52 +02:00
d1e5731d1d create POD dates pedido 2025-04-28 02:03:40 +02:00
029757bb40 add calendar festivos 2025-04-28 00:42:15 +02:00
bb4c9690b9 Merge branch 'feat/importador_rama' into 'main'
Feat/importador rama

See merge request jjimenez/safekat!750
2025-04-27 20:01:26 +00:00
6d45a950df Trabajando JS 2025-04-27 22:00:52 +02:00
6f8890a8b1 Merge branch 'main' into 'feat/importador_rama'
Main

See merge request jjimenez/safekat!749
2025-04-27 18:56:08 +00:00
c093c01c00 Merge branch 'main' into feat/festivos-calendar 2025-04-27 19:30:31 +02:00
a4532a7ff6 Merge branch 'fix/filter-datatable-ot' into 'main'
Fix/filter datatable ot

See merge request jjimenez/safekat!748
2025-04-27 17:27:30 +00:00
31a12ff343 try catch getTiempoProcesamientoHHMM 2025-04-27 19:26:02 +02:00
1d6f5fe53e default table encuadernacion 2025-04-27 19:24:11 +02:00
0b767c63e9 fix filter ferro 2025-04-27 19:13:06 +02:00
e464652fe2 festivo entity model 2025-04-27 19:01:23 +02:00
dd20f2a20e Merge branch 'maquinista-change-user' into 'main'
Maquinista change user

See merge request jjimenez/safekat!747
2025-04-27 16:54:35 +00:00
97554bffc9 add maquinista change user session 2025-04-27 18:53:24 +02:00
73e9e941ed Merge branch 'main' into maquinista-change-user 2025-04-27 12:25:09 +02:00
05720cf1ce Merge branch 'fix/migrate' into 'main'
fix migrate class name

See merge request jjimenez/safekat!746
2025-04-27 10:20:33 +00:00
04e9e3ee6f fix migrate class name 2025-04-27 12:18:20 +02:00
9804a6a927 change user session 2025-04-27 12:17:31 +02:00
3402e67fb2 Merge branch 'add/envio_ferros' into 'main'
Add/envio ferros

See merge request jjimenez/safekat!745
2025-04-27 10:14:05 +00:00
b1932e6f85 terminado envio de ferros 2025-04-27 12:12:52 +02:00
13ae70236e Merge branch 'feat/sk-44' into 'main'
Feat/sk 44

See merge request jjimenez/safekat!744
2025-04-27 09:00:23 +00:00
a0b5f3b4df trabajando en envio de ferros 2025-04-27 09:51:52 +02:00
0e444295e3 trabajando en el formulario envio de ferros 2025-04-27 09:51:04 +02:00
ae7707057a Cambiando titulo pagina 2025-04-27 09:17:46 +02:00
ff115f4f20 Configurando logica de captacion del Excel 2025-04-27 09:16:15 +02:00
ae456c8890 Implementado script principal 2025-04-27 00:00:58 +02:00
e8958dc893 Implementado menu lateral 2025-04-26 23:23:04 +02:00
b0ac132e59 Arreglado bug en archivo de migrate del catalogo 2025-04-26 23:05:15 +02:00
b50e564641 Desplegando arcihvos iniciales 2025-04-26 21:32:22 +02:00
894770d6ce Merge branch 'feat/importador_rama' of https://git.imnavajas.es/jjimenez/safekat into feat/importador_rama 2025-04-26 21:25:18 +02:00
367c7c2ea8 Merge branch 'main' into 'feat/importador_rama'
Main

See merge request jjimenez/safekat!743
2025-04-26 19:24:58 +00:00
9375b9b624 Añadiendo idiomas 2025-04-26 21:22:39 +02:00
033184cfa2 Iniciando herramienta de importacion desde catalogo 2025-04-26 16:52:59 +02:00
297 changed files with 40763 additions and 1295 deletions

View File

@ -100,9 +100,9 @@ class OrdenTrabajo extends BaseConfig
];
public array $OT_PLASTIFICADO_COLOR =
[
"BRIL" => ["bg" => "#00B0F0", "color" => "white"],
"BRILLO" => ["bg" => "#00B0F0", "color" => "white"],
"MATE" => ["bg" => "#FF0000", "color" => "white"],
"SOFT_TOUCH" => ["bg" => "#00B050", "color" => "white"],
"SOFT" => ["bg" => "#00B050", "color" => "white"],
"SANDY" => ["bg" => "#782170", "color" => "white"],
"ANTIRAYADO" => ["bg" => "#E97132", "color" => "white"],
"GOFRADO" => ["bg" => "#FFFF00", "color" => "black"],

Binary file not shown.

View File

@ -40,6 +40,8 @@ foreach (glob(APPPATH . 'Config/Routes/*Routes.php') as $routeFile) {
$routes->group('users', ['namespace' => 'App\Controllers\Configuracion'], function ($routes) {
$routes->get('', 'Users::index', ['as' => 'userList']);
$routes->get('maquinista/change/user','Users::index_maquinista_change_user',['as' => 'maquinistaUserChangeList']);
$routes->get('maquinista/change/session/(:num)','Users::change_user_session/$1',['as' => 'maquinistaChangeUserSession']);
$routes->get('list', 'Users::index', ['as' => 'userList2']);
$routes->get('add', 'Users::add', ['as' => 'newUser']);
$routes->post('add', 'Users::add', ['as' => 'createUser']);
@ -642,6 +644,7 @@ $routes->group('messages', ['namespace' => 'App\Controllers\Chat'], function ($r
$routes->get('datatable/presupuesto', 'ChatController::datatable_presupuesto_messages', ['as' => 'getDatatablePresupuestoMessages']);
$routes->get('datatable/pedido', 'ChatController::datatable_pedido_messages', ['as' => 'getDatatablePedidoMessages']);
$routes->get('datatable/factura', 'ChatController::datatable_factura_messages', ['as' => 'getDatatableFacturaMessages']);
$routes->get('datatable/ots', 'ChatController::datatable_ot_messages', ['as' => 'getDatatableOtMessages']);
$routes->post('direct', 'ChatController::store_new_direct_message', ['as' => 'storeNewDirectMessage']);
$routes->post('direct/client', 'ChatController::store_new_direct_message_client', ['as' => 'storeNewDirectMessageClient']);
@ -652,6 +655,8 @@ $routes->group('chat', ['namespace' => 'App\Controllers\Chat'], function ($route
$routes->get('presupuesto/(:num)', 'ChatController::get_chat_presupuesto_view/$1', ['as' => 'getChatPresupuestoView']);
$routes->get('pedido/(:num)', 'ChatController::get_chat_pedido_view/$1', ['as' => 'getChatPedidoView']);
$routes->get('factura/(:num)', 'ChatController::get_chat_factura_view/$1', ['as' => 'getChatFacturaView']);
$routes->get('ot/(:num)', 'ChatController::get_chat_ot_view/$1', ['as' => 'getChatOtView']);
$routes->get('direct/conversation/(:num)', 'ChatController::get_chat_direct/$1', ['as' => 'getChatDirect']);
$routes->get('direct/users/select/(:num)', 'ChatController::get_chat_direct_select_users/$1', ['as' => 'getChatDirectSelectUsers']);
@ -757,6 +762,7 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func
$routes->post("reset/date", 'Ordentrabajo::reset_orden_trabajo_date');
$routes->post("update/pedido/date", 'Ordentrabajo::update_orden_trabajo_pedido_date');
$routes->post("reset/pedido/date", 'Ordentrabajo::reset_orden_trabajo_pedido_date');
$routes->post("update/pod/pedido/date/(:num)",'Ordentrabajo::update_pod_pedido_dates/$1');
$routes->post("update/pedido", 'Ordentrabajo::update_orden_trabajo_pedido');
$routes->post("update/user", 'Ordentrabajo::update_orden_trabajo_user');
$routes->post("update", 'Ordentrabajo::update_orden_trabajo');
@ -807,6 +813,7 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi
$routes->get('print/label/test', 'LogisticaController::print_test_label');
$routes->get('panel', 'LogisticaController::panel', ['as' => 'LogisticaPanel']);
$routes->get('envios', 'LogisticaController::gestionEnvios', ['as' => 'gestionEnvios']);
$routes->get('enviosFerros', 'LogisticaController::gestionEnviosFerros', ['as' => 'gestionEnviosFerros']);
$routes->get('datatableEnvios', 'LogisticaController::datatable_envios');
$routes->get('datatableLineasEnvios/(:num)', 'LogisticaController::datatable_enviosEdit/$1');
$routes->get('envio/(:num)', 'LogisticaController::editEnvio/$1');
@ -821,6 +828,7 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi
$routes->post('updateProveedorEnvio', 'LogisticaController::updateProveedorEnvio');
$routes->post('finalizarEnvio', 'LogisticaController::finalizarEnvio');
$routes->post('generateEnvio', 'LogisticaController::generarEnvio');
$routes->post('generateEnvioFerro', 'LogisticaController::generarEnvioFerro');
$routes->get('selectForNewEnvio', 'LogisticaController::findForNewEnvio');
$routes->get('selectDireccionForEnvio', 'LogisticaController::selectDireccionForEnvio');
$routes->post('imprimirEtiquetas', 'LogisticaController::imprimirEtiquetas');

View File

@ -53,7 +53,6 @@ $routes->group('configuracion', ['namespace' => 'App\Controllers\Configuracion']
$routes->post('duplicate/(:num)', 'Papelesimpresion::duplicate/$1', ['as' => 'duplicatePapelImpresion']);
$routes->get('select', 'Papelesimpresion::papel_impresion_select', ['as' => 'papelImpresionSelect']);
$routes->get('show/(:num)', 'Papelesimpresion::papel_impresion_find/$1', ['as' => 'showPapelImpresion']);
});
/* Maquinas */
@ -149,5 +148,15 @@ $routes->group('configuracion', ['namespace' => 'App\Controllers\Configuracion']
$routes->group("messages", ["namespace" => 'App\Controllers\Chat'], function ($routes) {
$routes->get('', 'ChatController::config_view', ['as' => 'configMessagesIndex']);
});
});
/* Festivos */
$routes->group("festivos", ["namespace" => 'App\Controllers\Configuracion'], function ($routes) {
$routes->get('', 'FestivoController::index', ['as' => 'festivosList']);
$routes->post('', 'FestivoController::store_festivo_date', ['as' => 'storeFestivoDate']);
$routes->delete('(:num)', 'FestivoController::delete_festivo_date/$1', ['as' => 'deleteFestivoDate']);
$routes->get('all', 'FestivoController::find_all', ['as' => 'getFindAllFestivos']);
});
});

View File

@ -0,0 +1,25 @@
<?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');
$routes->post('importar-fila', 'ImportadorCatalogo::importarFila');
});
});

View File

@ -5,22 +5,13 @@ namespace App\Controllers\API;
use App\Controllers\Presupuestos\Presupuestocliente;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\API\ResponseTrait;
use App\Models\API\ItemModel;
class ImprimelibrosApi extends ResourceController
{
use ResponseTrait;
public function index()
{
$model = new ItemModel();
$data = $model->findAll();
return $this->respond($data);
}
public function calcular()
{
helper(['form']);

View File

@ -1,2 +0,0 @@
Portada Id Cliente Título Edición Autor Archivo ISBN EAN Páginas Acciones
Lo que hay que listar

View File

@ -222,6 +222,25 @@ class ChatController extends BaseController
return view(static::$viewPath . 'messageChatInternal', $this->viewData);
}
}
public function get_chat_ot_view($chat_id)
{
$chat = $this->chatModel->find($chat_id);
$this->viewData['breadcrumb'] = [
['title' => lang("Chat.chat"), 'route' => route_to("mensajeriaView"), 'active' => false],
['title' => $chat->title, 'route' => 'javascript:void(0);', 'active' => true]
];
$this->viewData["modelId"] = $chat->orden_trabajo_id;
$this->viewData["type"] = "ot";
$auth_user = auth()->user();
$this->chatModel->setAsViewedChatUserNotifications($chat_id, $auth_user->id);
$this->chatModel->setAsUnviewedChatUserMessages($chat_id, $auth_user->id);
if ($chat->chat_department_id) {
return view(static::$viewPath . 'messageChatFactura', $this->viewData);
} else {
return view(static::$viewPath . 'messageChatInternal', $this->viewData);
}
}
public function get_chat(int $chat_id)
{
@ -502,6 +521,23 @@ class ChatController extends BaseController
->toJson(true);
}
public function datatable_ot_messages()
{
$auth_user_id = auth()->user()->id;
$isAdmin = auth()->user()->inGroup('admin');
$query = $this->chatModel->getQueryDatatableMessageOrdenTrabajo($auth_user_id);
return DataTable::of($query)
->edit('created_at', fn($q) => $q->created_at ? Time::createFromFormat('Y-m-d H:i:s', $q->created_at)->format("d/m/Y H:i") : "")
->edit('updated_at', fn($q) => $q->updated_at ? Time::createFromFormat('Y-m-d H:i:s', $q->updated_at)->format("d/m/Y H:i") : "")
->edit("creator",fn($q) => $q->userId == $auth_user_id ? '<span class="badge text-bg-success w-100">'.lang("App.me").'</span>' : $q->creator)
->add("viewed", fn($q) => $this->chatModel->isMessageChatViewed($q->chatMessageId))
->add("action", fn($q) => ["type" => "ot", "modelId" => $q->id, "isAdmin" => $isAdmin,"chatMessageId" => $q->chatMessageId, "lang" => [
"view_chat" => lang('Chat.view_chat'),
"view_by_alt_message" => lang('Chat.view_by_alt_message')
]])
->toJson(true);
}
public function get_notifications_not_viewed_from_message(int $chat_message_id)
{
$unviewedNotifications = $this->chatModel->getUsersNotificationNotViewedFromChat($chat_message_id);

View File

@ -0,0 +1,103 @@
<?php
namespace App\Controllers\Configuracion;
use App\Controllers\BaseController;
use App\Controllers\BaseResourceController;
use App\Entities\Configuracion\FestivoEntity;
use App\Models\Collection;
use App\Entities\Configuracion\Imposicion;
use App\Models\Configuracion\FestivoModel;
use App\Models\Configuracion\ImposicionEsquemaModel;
use App\Models\Configuracion\ImposicionModel;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Validation\Validation;
use Hermawan\DataTables\DataTable;
use Psr\Log\LoggerInterface;
class FestivoController extends BaseController
{
protected $modelName = FestivoModel::class;
protected FestivoModel $model;
protected static $controllerSlug = 'festivos';
protected $format = 'json';
protected string $viewPath = 'themes/vuexy/form/configuracion/festivos/';
protected $indexRoute = 'festivoList';
protected array $viewData = [];
protected Validation $validation;
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
$this->viewData['pageTitle'] = lang('Festivos.moduleTitle');
$this->viewData['usingSweetAlert'] = true;
$this->model = model($this->modelName);
$this->validation = service("validation");
parent::initController($request, $response, $logger);
}
public function index()
{
return view($this->viewPath . $this->indexRoute);
}
public function store_festivo_date()
{
$bodyData = $this->request->getPost();
$date = $bodyData['date'];
$count = $this->model->where('date',$date)->countAllResults();
if ($count) {
$status = $this->model->where('date', $date)->delete(purge: true);
return $this->response->setJSON([
"message" => lang("App.user_alert_delete"),
"status" => $status,
]);
} else {
$status = $this->model->insert($bodyData);
if ($status) {
$festivoEntity = $this->model->find($status);
return $this->response->setJSON([
"message" => lang("App.global_alert_save_success"),
"status" => $status,
"data" => $festivoEntity
]);
} else {
return $this->response->setJSON([
"message" => lang("App.global_alert_save_error"),
"errors" => $this->model->errors(),
"status" => true
])->setStatusCode(400);
}
}
}
public function delete_festivo_date($id)
{
$status = $this->model->delete($id, true);
if ($status) {
return $this->response->setJSON([
"message" => lang("App.user_alert_delete"),
"status" => $status,
]);
} else {
return $this->response->setJSON([
"message" => lang("App.global_alert_save_error"),
"errors" => $this->model->errors(),
"status" => true
])->setStatusCode(400);
}
}
public function find_all()
{
$festivos = $this->model->findAll();
return $this->response->setJSON([
"message" => lang("App.global_alert_fetch_success"),
"status" => true,
"data" => $festivos
]);
}
}

View File

@ -1,4 +1,6 @@
<?php namespace App\Controllers\Configuracion;
<?php
namespace App\Controllers\Configuracion;
use App\Entities\Usuarios\UserEntity;
use App\Models\Chat\ChatDeparmentModel;
@ -54,7 +56,6 @@ class Users extends \App\Controllers\GoBaseController
];
parent::initController($request, $response, $logger);
}
public function index()
@ -87,7 +88,7 @@ class Users extends \App\Controllers\GoBaseController
// Marcar el username como NULL
$sanitizedData = $this->sanitized($postData, true);
$noException = true;
// Obtener proveedor de usuarios
@ -118,11 +119,10 @@ class Users extends \App\Controllers\GoBaseController
} // Email is not unique!
else {
$this->viewData['errorMessage'] = "El correo '". $sanitizedData['email'] ."' ya está registrado en el sistema";
$this->viewData['errorMessage'] = "El correo '" . $sanitizedData['email'] . "' ya está registrado en el sistema";
$this->session->setFlashdata('formErrors', $this->model->errors());
$successfulResult = false; // Hacked
}
} catch (\Exception $e) {
$noException = false;
$this->viewData['errorMessage'] = $e->getMessage();
@ -234,7 +234,6 @@ class Users extends \App\Controllers\GoBaseController
} else {
$successfulResult = $this->model->skipValidation(true)->update($id, $sanitizedData);
}
} catch (\Exception $e) {
$noException = false;
$this->dealWithException($e);
@ -319,8 +318,6 @@ class Users extends \App\Controllers\GoBaseController
$message = "Usuario eliminado correctamente";
return $this->redirect2listView('successMessage', $message);
} // end function delete(...)
@ -374,9 +371,10 @@ class Users extends \App\Controllers\GoBaseController
}
}
public function datatable(){
public function datatable()
{
if($this->request->isAJAX()){
if ($this->request->isAJAX()) {
$reqData = $this->request->getPost();
if (!isset($reqData['draw']) || !isset($reqData['columns'])) {
@ -405,7 +403,6 @@ class Users extends \App\Controllers\GoBaseController
$this->model->getResource([])->countAllResults(),
$this->model->getResource($searchValues)->countAllResults()
));
} else {
return $this->failUnauthorized('Invalid request', 403);
}
@ -447,4 +444,27 @@ class Users extends \App\Controllers\GoBaseController
return $data;
}
public function index_maquinista_change_user()
{
$this->viewData['breadcrumb'] = [
['title' => lang("App.menu_change_session"), 'route' => route_to('maquinistaUserChangeList'), 'active' => true]
];
$maquinistas = [];
$users = auth()->getProvider()->whereNotIn('id',[auth()->user()->id])->findAll();
foreach ($users as $key => $user) {
if ($user->inGroup('maquina') && !$user->inGroup('admin', 'comercial', 'cliente-editor', 'cliente-admin')) {
$maquinistas[] = $user;
}
}
$this->viewData['maquinistas'] = $maquinistas;
return view('/themes/vuexy/form/produccion/maquinista/viewMaquinistaCambioUserList.php', $this->viewData);
}
public function change_user_session(int $user_id)
{
// Check the credentials
$user = auth()->getProvider()->findById($user_id);
auth()->logout();
auth()->login($user);
return redirect("home");
}
}

View File

@ -0,0 +1,314 @@
<?php
namespace App\Controllers\Importadores;
use App\Controllers\BaseResourceController;
use App\Entities\Catalogo\CatalogoLibroEntity;
use App\Models\Catalogo\CatalogoLibroModel;
use App\Controllers\Presupuestos\Presupuestocliente;
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 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'
]);
}
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
]
];
// Ajuste del precio a RAMA
$dataToUpdate = [
'total_aceptado' => ($tirada * $precio_compra),
'total_aceptado_revisado' => ($tirada * $precio_compra),
'total_precio_unidad' => $precio_compra
];
$presupuestoModel = model('App\Models\Presupuestos\Presupuestomodel');
$presupuestoModel->update($response['data']['sk_id'], $dataToUpdate);
return $this->respond($response);
} catch (\Exception $e) {
return $this->respond([
'status' => 500,
'error' => 'Server error',
'message' => 'Error inesperado durante el procesado',
'debug' => $e->getMessage()
]);
}
}
}

View File

@ -62,6 +62,22 @@ class LogisticaController extends BaseController
'currentModule' => static::$controllerSlug,
'boxTitle' => lang('Logistica.gestionEnvios'),
'usingServerSideDataTable' => true,
'tipo_envio' => 'estandar',
];
$viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class
return view(static::$viewPath . 'viewLogisticaSelectEnvios', $viewData);
}
public function gestionEnviosFerros()
{
$viewData = [
'currentModule' => static::$controllerSlug,
'boxTitle' => lang('Logistica.envioFerros'),
'usingServerSideDataTable' => true,
'tipo_envio' => 'ferro_prototipo',
];
$viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class
@ -85,7 +101,14 @@ class LogisticaController extends BaseController
{
if ($this->request->isAJAX()) {
$query = LogisticaService::findForNewEnvio();
$tipo_envio = $this->request->getGet('tipo_envio') ?? 'estandar';
if($tipo_envio == 'ferro_prototipo'){
$query = LogisticaService::findForNewEnvioFerro();
} else {
$query = LogisticaService::findForNewEnvio();
}
if ($this->request->getGet("q")) {
$query->groupStart()
->orLike("id", $this->request->getGet("q"))
@ -105,12 +128,12 @@ class LogisticaController extends BaseController
public function selectDireccionForEnvio(){
if ($this->request->isAJAX()) {
$pedido_id = $this->request->getGet('pedido_id');
if($pedido_id == null || $pedido_id == 0){
$ot = $this->request->getGet('ot_id');
if($ot == null || $ot == 0){
return [];
}
$searchVal = $this->request->getGet("q") ?? "";
$result = LogisticaService::findDireccionesNewEnvio($pedido_id, $searchVal);
$result = LogisticaService::findDireccionesNewEnvio($ot, $searchVal);
return $this->response->setJSON($result);
} else {
@ -124,9 +147,22 @@ class LogisticaController extends BaseController
{
if ($this->request->isAJAX()) {
$pedido_id = $this->request->getPost('pedido_id');
$direccion = $this->request->getPost('direccion');
$result = LogisticaService::generateEnvio($pedido_id, $direccion);
$ot_id = $this->request->getPost('ot_id');
$direccion = $this->request->getPost('direccion') ?? "";
$result = LogisticaService::generateEnvio($ot_id, $direccion);
return $this->response->setJSON($result);
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function generarEnvioFerro()
{
if ($this->request->isAJAX()) {
$ot_id = $this->request->getPost('ot_id');
$result = LogisticaService::generateEnvioFerro($ot_id);
return $this->response->setJSON($result);
} else {
return $this->failUnauthorized('Invalid request', 403);
@ -172,7 +208,7 @@ class LogisticaController extends BaseController
}
$modelImpresora = model('App\Models\Configuracion\ImpresoraEtiquetaModel');
$impresora = $modelImpresora->select('id, name')
$impresora = $modelImpresora->select('id, name, ip, port, user, pass')
->where('deleted_at', null)
->where('id', $printer_id)
->orderBy('name', 'asc')
@ -233,9 +269,10 @@ class LogisticaController extends BaseController
{
$otsFilter = $this->request->getGetPost('otsFilter');
$tipo_envio = $this->request->getGetPost('tipo_envio') ?? 'estandar';
$model = model('App\Models\Logistica\EnvioModel');
$q = $model->getDatatableQuery();
$q = $model->getDatatableQuery($tipo_envio);
if (!empty($otsFilter)) {
$q->groupStart();
@ -370,7 +407,7 @@ class LogisticaController extends BaseController
)->edit(
"unidadesEnvio",
function ($row, $meta) {
if($row->finalizado == 1){
if($row->finalizado == 1 || $row->tipo_envio == 'ferro_prototipo'){
return $row->unidadesEnvio;
}
return '<input type="number" class="form-control input-lineas input-unidades text-center"

View File

@ -54,6 +54,7 @@ class Presupuestodirecciones extends \App\Controllers\BaseResourceController
$proveedor = $reqData['proveedor'] ?? "";
$proveedor_id = $reqData['proveedor_id'] ?? "";
$entregaPieCalle = $reqData['entregaPieCalle'] ?? 0;
$is_ferro_prototipo = $reqData['is_ferro_prototipo'] ?? 0;
$data = [
"presupuesto_id" => $presupuesto_id,
@ -73,6 +74,7 @@ class Presupuestodirecciones extends \App\Controllers\BaseResourceController
"proveedor" => $proveedor,
"proveedor_id" => $proveedor_id,
"entregaPieCalle" => $entregaPieCalle,
"is_ferro_prototipo" => $is_ferro_prototipo
];
$response = $this->model->insert($data);

View File

@ -105,11 +105,11 @@ class Ordentrabajo extends BaseController
public function update_orden_trabajo_tarea()
{
$bodyData = $this->request->getPost();
return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "data" => $bodyData]);
$validated = $this->validation->run($bodyData, "orden_trabajo_tarea");
if ($validated) {
$r = $this->produccionService->updateOrdenTrabajoTarea($bodyData["orden_trabajo_tarea_id"], $bodyData);
return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $bodyData]);
$tareaEntity = $this->otTarea->find($bodyData["orden_trabajo_tarea_id"]);
return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $tareaEntity]);
} else {
return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
}
@ -242,7 +242,7 @@ class Ordentrabajo extends BaseController
{
$logo = config(LogoImpresion::class);
$q = $this->otModel->getDatatableQuery()->where("ferro_ok_at", null);
$q = $this->otModel->getDatatableQuery()->where('presupuestos.ferro',1)->where("ferro_ok_at", null);
// return $this->response->setJSON($q->get()->getResultArray());
return DataTable::of($q)
->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" => $this->produccionService->init($q->id)->getOtColorStatus()])
@ -257,7 +257,7 @@ class Ordentrabajo extends BaseController
{
$logo = config(LogoImpresion::class);
$q = $this->otModel->getDatatableQuery()->where("ferro_ok_at is NOT NULL", NULL, FALSE);
$q = $this->otModel->getDatatableQuery()->where('presupuestos.ferro',1)->where("ferro_ok_at is NOT NULL", NULL, FALSE);
// return $this->response->setJSON($q->get()->getResultArray());
return DataTable::of($q)
->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" => $this->produccionService->init($q->id)->getOtColorStatus()])
@ -585,4 +585,17 @@ class Ordentrabajo extends BaseController
];
return $this->response->setJSON($data);
}
public function update_pod_pedido_dates($orden_trabajo_id)
{
$this->produccionService->init($orden_trabajo_id);
if($this->produccionService->isPOD){
$status = $this->produccionService->updatePodDates();
return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $status, "data" => $this->produccionService->getPedido()]);
}else{
return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => false, "data" => $this->produccionService->getPedido()]);
}
}
}

View File

@ -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);

View File

@ -7,30 +7,24 @@ use CodeIgniter\Database\Migration;
use CodeIgniter\Database\RawSql;
use CodeIgniter\I18n\Time;
class AddClickColumnOrdenTrabajoTarea extends Migration
class AddFerroProtoPresupuestoDirecciones extends Migration
{
protected array $COLUMNS = [
"click_init" => [
"type" => "INT",
"is_ferro_prototipo" => [
"type" => "TINYINT",
"unsigned" => true,
"default" => 0,
"comment" => "Click iniciales de una tarea de impresion"
],
"click_end" => [
"type" => "INT",
"unsigned" => true,
"default" => 0,
"comment" => "Click finales de una tarea de impresion"
"comment" => "Indica si es una direccion para el prototipo o ferro",
],
];
public function up()
{
$this->forge->addColumn('orden_trabajo_tareas', $this->COLUMNS);
$this->forge->addColumn('presupuesto_direcciones', $this->COLUMNS);
}
public function down()
{
$this->forge->dropColumn('orden_trabajo_tareas', array_keys($this->COLUMNS));
$this->forge->dropColumn('presupuesto_direcciones', array_keys($this->COLUMNS));
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Database\Migrations;
use App\Models\OrdenTrabajo\OrdenTrabajoTarea;
use CodeIgniter\Database\Migration;
use CodeIgniter\Database\RawSql;
use CodeIgniter\I18n\Time;
class AddTipoEnvioEnvios extends Migration
{
protected array $COLUMNS = [
"tipo_envio" => [
"type" => "enum",
"constraint" => ['estandar', 'ferro_prototipo'],
"default" => 'estandar',
"comment" => "Indica el tipo de envio",
],
];
public function up()
{
$this->forge->addColumn('envios', $this->COLUMNS);
}
public function down()
{
$this->forge->dropColumn('envios', array_keys($this->COLUMNS));
}
}

View File

@ -4,7 +4,7 @@ namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddPliegoColumnOrdenTrabajoTarea extends Migration
class AlterFkOrdenTrabajoTareaProgressDates extends Migration
{

View File

@ -0,0 +1,49 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\RawSql;
use CodeIgniter\Database\Migration;
class CreateTableFestivos extends Migration
{
protected array $COLUMNS = [
"id" => [
"type" => "INT",
"unsigned" => true,
"auto_increment" => true
],
"date" => [
"type" => "DATE",
"unique" => true,
],
];
public function up()
{
$this->forge->addField($this->COLUMNS);
$currenttime = new RawSql("CURRENT_TIMESTAMP");
$this->forge->addField([
"created_at" => [
"type" => "TIMESTAMP",
"default" => $currenttime,
],
"updated_at" => [
"type" => "TIMESTAMP",
"null" => true,
],
"deleted_at" => [
"type" => "TIMESTAMP",
"null" => true,
],
]);
$this->forge->addPrimaryKey('id');
$this->forge->createTable("festivos", true);
}
public function down()
{
//
$this->forge->dropTable("festivos", true);
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AlterTarifasAcabadoAddBoleanColumns extends Migration
{
protected array $COLUMNS = [
'plastificado' => [
'type' => 'BOOLEAN',
'default' => false,
],
'plakene' => [
'type' => 'BOOLEAN',
'default' => false,
],
'rectractilado' => [
'type' => 'BOOLEAN',
'default' => false,
],
'estampado' => [
'type' => 'BOOLEAN',
'default' => false,
],
'uvi' => [
'type' => 'BOOLEAN',
'default' => false,
],
'plastificado_tipo' => [
'type' => 'ENUM',
'constraint' => ['BRILLO','MATE','SANDY','GOFRADO','SOFT','ANTIRAYADO'],
'null' => true,
],
'plakene_tipo' => [
'type' => 'ENUM',
'constraint' => ['TRASLUCIDO','MATE','NEGRO'],
'null' => true,
],
'rectractilado_tipo' => [
'type' => 'ENUM',
'constraint' => ['1','3','5'],
'null' => true,
],
'estampado_tipo' => [
'type' => 'ENUM',
'constraint' => ['ORO','PLATA','COBRE','BRONCE'],
'null' => true,
],
'uvi_tipo' => [
'type' => 'ENUM',
'constraint' => ['2D','3D','BRAILLE'],
'null' => true,
]
];
public function up()
{
$this->forge->addColumn('lg_tarifa_acabado',$this->COLUMNS);
}
public function down()
{
$this->forge->dropColumn('lg_tarifa_acabado',array_keys($this->COLUMNS));
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace App\Database\Seeds;
use App\Models\Configuracion\ConfigVariableModel;
use App\Models\Configuracion\MaquinaTareaModel;
use CodeIgniter\Database\Seeder;
class PedidoPodSeeder extends Seeder
{
public function run()
{
$m = model(ConfigVariableModel::class);
$data = [
[
"name" => "pod_impresion_dias_tras_confirmacion",
"value" => 1,
"description" => "Días a los que se establece la fecha de impresion en pedido tras confirmación"
],
[
"name" => "pod_encuadernacion_dias_tras_confirmacion",
"value" => 2,
"description" => "Días a los que se establece la fecha de encuadernación en pedido tras confirmación"
],
[
"name" => "pod_entrega_real_dias_tras_confirmacion",
"value" => 5,
"description" => "Días a los que se establece la fecha entrega real en pedido tras confirmación"
],
[
"name" => "pod_embalaje_dias_tras_confirmacion",
"value" => 4,
"description" => "Días a los que se establece la fecha de encuadernación en pedido tras confirmación"
],
];
foreach ($data as $key => $row) {
if($m->getVariable($row['name']) == null)
{
$m->insert($row);
}
}
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace App\Entities\Configuracion;
use CodeIgniter\Entity\Entity;
class FestivoEntity extends Entity
{
protected $attributes = [
"id" => null,
"date" => null,
];
protected $casts = [];
}

View File

@ -31,5 +31,6 @@ class EnvioEntity extends Entity
'created_at' => 'datetime',
'updated_at' => 'datetime',
'cajas' => 'int',
'tipo_envio' => 'string',
];
}

View File

@ -1,7 +1,9 @@
<?php
namespace App\Entities\Presupuestos;
use App\Entities\Compras\ProveedorEntity;
use App\Entities\Tarifas\Acabados\TarifaAcabadoEntity;
use App\Models\Compras\ProveedorModel;
use App\Models\Configuracion\MaquinaModel;
use App\Models\Tarifas\Acabados\TarifaAcabadoModel;
use App\Models\Tarifas\Maquinas\TarifaAcabadoMaquinaModel;
@ -54,5 +56,13 @@ class PresupuestoAcabadosEntity extends \CodeIgniter\Entity\Entity
$m = model(TarifaAcabadoModel::class);
return $m->find($this->attributes["tarifa_acabado_id"]);
}
public function proveedor(): ?ProveedorEntity
{
$proveedor = null;
$m = model(ProveedorModel::class);
if ($this->attributes["proveedor_id"]) {
$proveedor = $m->find($this->attributes["proveedor_id"]);
}
return $proveedor;
}
}

View File

@ -25,6 +25,7 @@ class PresupuestoDireccionesEntity extends \CodeIgniter\Entity\Entity
"proveedor_id" => null,
"margen" => null,
"entregaPieCalle" => null,
"is_ferro_prototipo" => null,
];
protected $casts = [
"presupuesto_id" => "int",
@ -38,6 +39,7 @@ class PresupuestoDireccionesEntity extends \CodeIgniter\Entity\Entity
"margen" => "float",
"proveedor_id" => "int",
"entregaPieCalle" => "int",
"is_ferro_prototipo" => "int",
];
}

View File

@ -1,7 +1,10 @@
<?php
namespace App\Entities\Presupuestos;
use App\Entities\Compras\ProveedorEntity;
use App\Entities\Tarifas\TarifaEncuadernacionEntity;
use App\Models\Compras\ProveedorModel;
use App\Models\Configuracion\MaquinaModel;
use App\Models\Tarifas\Maquinas\TarifaEncuadernacionMaquinaModel;
use App\Models\Tarifas\TarifaEncuadernacionModel;
@ -32,10 +35,10 @@ class PresupuestoEncuadernacionesEntity extends \CodeIgniter\Entity\Entity
"precio_total" => "float",
"margen" => "float",
];
public function maquinas() : array
public function maquinas(): array
{
$m = model(TarifaEncuadernacionMaquinaModel::class);
$tarifa_maquinas = $m->where("tarifa_encuadernacion_id",$this->attributes["tarifa_encuadernado_id"])->findAll();
$tarifa_maquinas = $m->where("tarifa_encuadernacion_id", $this->attributes["tarifa_encuadernado_id"])->findAll();
$maquinaModel = model(MaquinaModel::class);
$maquinas = [];
foreach ($tarifa_maquinas as $key => $tarifa_maquina) {
@ -43,9 +46,18 @@ class PresupuestoEncuadernacionesEntity extends \CodeIgniter\Entity\Entity
}
return $maquinas;
}
public function tarifa() : TarifaEncuadernacionEntity
public function tarifa(): TarifaEncuadernacionEntity
{
$m = model(TarifaEncuadernacionModel::class);
return $m->find($this->attributes["tarifa_encuadernado_id"]);
}
public function proveedor(): ?ProveedorEntity
{
$proveedor = null;
$m = model(ProveedorModel::class);
if ($this->attributes["proveedor_id"]) {
$proveedor = $m->find($this->attributes["proveedor_id"]);
}
return $proveedor;
}
}

View File

@ -210,35 +210,35 @@ class PresupuestoEntity extends \CodeIgniter\Entity\Entity
$q = $model->where('presupuesto_id', $this->attributes["id"])->findAll();
return $q ?? [];
}
/**
* Obtiene las lineas de presupuesto del actual presupuesto
*
* @return ?PresupuestoLineaEntity
*/
public function presupuestoLineaImpresion(): ?PresupuestoLineaEntity
{
$model = model(PresupuestoLineaModel::class);
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo", ["lp_rot_bn", "lp_rot_color", "lp_color", "lp_colorhq", "lp_bn", "lp_bnhq"])->first();
return $q;
}
/**
/**
* Obtiene las lineas de presupuesto del actual presupuesto
*
* @return PresupuestoLineaEntity
*/
public function presupuestoLineaImpresion(): PresupuestoLineaEntity
public function presupuestoLineaCubierta(): ?PresupuestoLineaEntity
{
$model = model(PresupuestoLineaModel::class);
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo",["lp_rot_bn","lp_rot_color","lp_color","lp_colorhq","lp_bn","lp_bnhq"])->first();
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo", ["lp_cubierta"])->first();
return $q;
}
/**
* Obtiene las lineas de presupuesto del actual presupuesto
*
* @return PresupuestoLineaEntity
*/
public function presupuestoLineaCubierta(): PresupuestoLineaEntity
{
$model = model(PresupuestoLineaModel::class);
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo",["lp_cubierta"])->first();
return $q;
}
/**
/**
* Obtiene las lineas de presupuesto del actual presupuesto
*
* @return PresupuestoLineaEntity
@ -247,70 +247,81 @@ class PresupuestoEntity extends \CodeIgniter\Entity\Entity
{
$model = model(PresupuestoLineaModel::class);
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo",["lp_sobrecubierta"])->first();
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo", ["lp_sobrecubierta"])->first();
return $q;
}
public function hasSobrecubierta() : bool
public function presupuestoLineaGuarda(): ?PresupuestoLineaEntity
{
$model = model(PresupuestoLineaModel::class);
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo", ["lp_guardas"])->first();
return $q;
}
public function hasSobrecubierta(): bool
{
$hasSobrecubierta = false;
$model = model(PresupuestoLineaModel::class);
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo",["lp_sobrecubierta"])->countAllResults();
if($q > 0){
$q = $model->where('presupuesto_id', $this->attributes["id"])->whereIn("tipo", ["lp_sobrecubierta"])->countAllResults();
if ($q > 0) {
$hasSobrecubierta = true;
}
return $hasSobrecubierta;
}
public function cliente() : ClienteEntity
public function cliente(): ?ClienteEntity
{
$m = model(ClienteModel::class);
return $m->find($this->attributes["cliente_id"]);
if ($this->attributes['cliente_id']) {
return $m->find($this->attributes["cliente_id"]);
} else {
return null;
}
}
public function encuadernaciones(): array
{
$m = model(PresupuestoEncuadernacionesModel::class);
return $m->where("presupuesto_id",$this->attributes["id"])->findAll();
return $m->where("presupuesto_id", $this->attributes["id"])->findAll();
}
public function acabados(): array
{
$m = model(PresupuestoAcabadosModel::class);
return $m->where("presupuesto_id",$this->attributes["id"])->findAll();
return $m->where("presupuesto_id", $this->attributes["id"])->findAll();
}
public function preimpresiones(): array
{
$m = model(PresupuestoPreimpresionesModel::class);
return $m->where("presupuesto_id",$this->attributes["id"])->findAll();
return $m->where("presupuesto_id", $this->attributes["id"])->findAll();
}
public function manipulados(): array
{
$m = model(PresupuestoManipuladosModel::class);
return $m->where("presupuesto_id",$this->attributes["id"])->findAll();
return $m->where("presupuesto_id", $this->attributes["id"])->findAll();
}
public function extras(): array
{
$m = model(PresupuestoServiciosExtraModel::class);
return $m->where("presupuesto_id",$this->attributes["id"])->findAll();
return $m->where("presupuesto_id", $this->attributes["id"])->findAll();
}
public function papel_formato() : PapelFormatoEntity
public function papel_formato(): PapelFormatoEntity
{
$m = model(PapelFormatoModel::class);
return $m->find($this->attributes["papel_formato_id"]);
}
public function files(): array
public function files(): array
{
$m = model(PresupuestoFicheroModel::class);
$files = $m->where('presupuesto_id',$this->attributes['id'])->findAll();
$files = $m->where('presupuesto_id', $this->attributes['id'])->findAll();
return $files ?? [];
}
public function tipo_presupuesto() : ?TipoPresupuestoEntity
public function tipo_presupuesto(): ?TipoPresupuestoEntity
{
$tipo_presupuesto = null;
$m = model(TipoPresupuestoModel::class);
if($this->attributes["tipo_impresion_id"]){
if ($this->attributes["tipo_impresion_id"]) {
$tipo_presupuesto = $m->find($this->attributes['tipo_impresion_id']);
}
return $tipo_presupuesto;
}
}

View File

@ -24,6 +24,16 @@ class TarifaAcabadoEntity extends \CodeIgniter\Entity\Entity
"deleted_at" => null,
"created_at" => null,
"updated_at" => null,
'plastificado' => false,
'plakene' => false,
'rectractilado' => false,
'estampado' => false,
'uvi' => false,
'plastificado_tipo' => null,
'plakene_tipo' => null,
'rectractilado_tipo' => null,
'estampado_tipo' => null,
'uvi_tipo' => null,
];
protected $casts = [
"precio_min" => "float",
@ -33,6 +43,16 @@ class TarifaAcabadoEntity extends \CodeIgniter\Entity\Entity
"user_created_id" => "int",
"user_updated_id" => "int",
"is_deleted" => "int",
'plastificado' => 'boolean',
'plakene' => 'boolean',
'rectractilado' => 'boolean',
'estampado' => 'boolean',
'uvi' => 'boolean',
'plastificado_tipo' => '?string',
'plakene_tipo' => '?string',
'rectractilado_tipo' => '?string',
'estampado_tipo' => '?string',
'uvi_tipo' => '?string',
];
/**
* Devuelve las maquinas asociadas a esta tarifa de acabado
@ -48,6 +68,7 @@ class TarifaAcabadoEntity extends \CodeIgniter\Entity\Entity
public function isUVI(): bool
{
return in_array($this->attributes["code"],["R3D","R2D"]);
return $this->attributes['uvi'];
}
}

View File

@ -676,6 +676,7 @@ return [
"menu_tarifacliente" => "Fees",
"menu_configuration" => "Settings",
"menu_config_holidays" => "Holidays",
"menu_calendario" => "Calendar",
"menu_paises" => "Countries",
"menu_correo" => "Mail",
@ -699,7 +700,7 @@ return [
"menu_digitalizacion" => "Digitalisation",
"menu_importacion" => "Import",
"menu_importadores" => "Import",
"menu_catalogo" => "Catalogue",
"menu_catalogo_libros" => "Books",
@ -761,6 +762,7 @@ return [
"menu_tarifaimpresion" => "Printing",
"menu_users" => "Users",
"menu_change_session" => "Seleccionar turno",
"menu_permission_group" => "Roles and permissions",
"menu_registration" => "Registration",

View File

@ -0,0 +1,7 @@
<?php
return [
'date' => 'Date',
'moduleTitle' => 'Holidays'
];

View File

@ -690,6 +690,7 @@ return [
"menu_configuration" => "Configuración",
"menu_variables" => "Variables sistema",
"menu_config_messages" => "Mensajería",
"menu_config_holidays" => "Festivos",
"menu_error_presupuesto" => "Errores presupuesto",
"menu_calendario" => "Calendario",
"menu_paises" => "Paises",
@ -719,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",

View File

@ -0,0 +1,7 @@
<?php
return [
'date' => 'Fecha',
'moduleTitle' => 'Festivos'
];

View 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:',
];

View File

@ -67,6 +67,11 @@ return [
'vencimientosPermission' => 'Vencimientos',
"ticketsSection" => "Tickets",
'produccionSection' => 'Producción',
'catalogoSection' => 'Catálogo',
'importadoresSection' => 'Importadores',
'catalogoPermission' => 'Desde catálogo',
'validation' => [
'id' => [

View File

@ -0,0 +1,72 @@
<?php
namespace App\Models\Configuracion;
use App\Entities\Configuracion\FestivoEntity;
use App\Models\BaseModel;
class FestivoModel extends BaseModel
{
protected $table = "festivos";
protected $primaryKey = 'id';
protected $allowedFields = ["date"];
protected $returnType = FestivoEntity::class;
protected $useAutoIncrement = true;
protected $useSoftDeletes = true;
protected $protectFields = true;
protected bool $allowEmptyInserts = false;
protected bool $updateOnlyChanged = true;
protected array $casts = [];
protected array $castHandlers = [];
// Dates
protected $useTimestamps = true;
protected $dateFormat = 'datetime';
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $deletedField = 'deleted_at';
// Validation
protected $skipValidation = false;
protected $cleanValidationRules = true;
// Callbacks
protected $allowCallbacks = true;
protected $beforeInsert = [];
protected $afterInsert = [];
protected $beforeUpdate = [];
protected $afterUpdate = [];
protected $beforeFind = [];
protected $afterFind = [];
protected $beforeDelete = [];
protected $afterDelete = [];
protected $validationRules = [
"date" => [
"label" => "Festivos.date",
"rules" => "required|valid_date[Y-m-d]",
],
];
protected $validationMessages = [
"date" => [
"valid_date" => "Validation.valid_date",
],
];
public function isFestivo($date)
{
return $this->where('date',$date)->countAllResults() > 0 ? true : false;
}
}

View File

@ -37,7 +37,7 @@ class EnvioLineaModel extends Model
->select(
"t1.id, t1.pedido_id as pedido, t3.id as presupuesto,
t3.titulo as titulo, t1.unidades_envio as unidadesEnvio, t1.unidades_envio as unidadesEnvioRaw,
t1.unidades_total as unidadesTotal,
t1.unidades_total as unidadesTotal, t2.tipo_envio as tipo_envio,
IFNULL((
SELECT SUM(t_sub.unidades_envio)
FROM envios_lineas t_sub

View File

@ -32,13 +32,14 @@ class EnvioModel extends Model
'created_at',
'updated_at',
'cajas',
'tipo_envio',
];
protected $useTimestamps = true;
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
public function getDatatableQuery(): BaseBuilder
public function getDatatableQuery($tipo_envio = "estandar"): BaseBuilder
{
$builder = $this->db
->table($this->table . " t1")
@ -51,6 +52,24 @@ class EnvioModel extends Model
$builder->join("lg_paises t3", "t3.id = t1.pais_id", "left");
$builder->join("pedidos t4", "t4.id = t2.pedido_id", "left");
$builder->join('ordenes_trabajo t5', 't5.pedido_id = t4.id');
$builder->where("t1.tipo_envio", $tipo_envio);
$builder->groupBy("t1.id");
return $builder;
}
public function getDatatableQueryFerroPrototipo(): BaseBuilder
{
$builder = $this->db
->table($this->table . " t1")
->select(
"t1.id, GROUP_CONCAT(DISTINCT t5.id) AS ots,
t1.att, t1.direccion, t1.ciudad, t3.nombre as pais, t1.cp, t1.email, t1.telefono, t1.finalizado"
);
$builder->join("lg_paises t3", "t3.id = t1.pais_id", "left");
$builder->join("pedidos t4", "t4.id = t2.pedido_id", "left");
$builder->join('ordenes_trabajo t5', 't5.pedido_id = t4.id');
$builder->whereIn("t1.tipo_envio", ["estandar"]);
$builder->groupBy("t1.id");
return $builder;

View File

@ -45,6 +45,7 @@ class PresupuestoDireccionesModel extends \App\Models\BaseModel
"proveedor_id",
"proveedor",
"entregaPieCalle",
"is_ferro_prototipo"
];
protected $returnType = "App\Entities\Presupuestos\PresupuestoDireccionesEntity";
@ -69,7 +70,8 @@ class PresupuestoDireccionesModel extends \App\Models\BaseModel
t1.email AS email, t1.direccion AS direccion, t1.pais_id AS pais_id, t2.nombre AS pais,
t1.municipio AS municipio, t1.provincia AS provincia, t1.cp AS cp, t1.telefono AS telefono,
t1.peso AS peso, t1.cantidad AS cantidad, t1.precio AS precio, t1.margen AS margen,
t1.proveedor_id AS proveedor_id, t1.proveedor AS proveedor, t1.entregaPieCalle AS entregaPieCalle"
t1.proveedor_id AS proveedor_id, t1.proveedor AS proveedor, t1.entregaPieCalle AS entregaPieCalle,
t1.is_ferro_prototipo AS is_ferro_prototipo"
);
$builder->where('t1.presupuesto_id', $presupuesto_id);

View File

@ -1,4 +1,5 @@
<?php
namespace App\Models\Tarifas\Acabados;
class TarifaAcabadoModel extends \App\Models\BaseModel
@ -33,6 +34,16 @@ class TarifaAcabadoModel extends \App\Models\BaseModel
"is_deleted",
"user_created_id",
"user_updated_id",
'plastificado',
'plakene',
'rectractilado',
'estampado',
'uvi',
'plastificado_tipo',
'plakene_tipo',
'rectractilado_tipo',
'estampado_tipo',
'uvi_tipo'
];
protected $returnType = 'App\Entities\Tarifas\Acabados\TarifaAcabadoEntity';
@ -96,9 +107,9 @@ class TarifaAcabadoModel extends \App\Models\BaseModel
return empty($search)
? $builder
: $builder
->groupStart()
->like("t1.nombre", $search)
->groupEnd();
->groupStart()
->like("t1.nombre", $search)
->groupEnd();
}
public function getServiciosAcabadoSelector()

View File

@ -94,6 +94,7 @@ class LogisticaService
WHERE el.pedido_id = p.id
AND el.presupuesto_id = pr.id
AND e.finalizado = 1
AND e.tipo_envio = 'estandar'
) AS unidades_enviadas,
pd.cantidad AS cantidad
")
@ -115,7 +116,47 @@ class LogisticaService
return $builder;
}
public static function findDireccionesNewEnvio($pedido_id, $searchVal = "")
public static function findForNewEnvioFerro()
{
$db = \Config\Database::connect();
// 3. Subconsulta principal
$subBuilder = $db->table('pedidos_linea pl')
->select("
ot.id AS id,
CONCAT('[', ot.id, '] - ', pr.titulo) AS name,
p.id as pedido_id,
pr.id as presupuesto_id
")
->join('pedidos p', 'p.id = pl.pedido_id')
->join('presupuestos pr', 'pr.id = pl.presupuesto_id')
->join('presupuesto_direcciones pd', 'pd.presupuesto_id = pr.id')
->join('ordenes_trabajo ot', 'ot.pedido_id = p.id')
->join('orden_trabajo_dates ot_dates', 'ot_dates.orden_trabajo_id = ot.id')
->whereIn('p.estado', ['finalizado', 'produccion'])
->where('ot_dates.pendiente_ferro_at IS NOT NULL')
->where('pd.is_ferro_prototipo', 1)
->groupBy('pl.id');
// 4. Envolver y filtrar por unidades pendientes
$builder = $db->table("({$subBuilder->getCompiledSelect(false)}) AS sub");
$builder->select('id, name');
$builder->orderBy('name', 'ASC');
$builder->where("
NOT EXISTS (
SELECT 1
FROM envios e
INNER JOIN envios_lineas le ON le.envio_id = e.id
WHERE e.tipo_envio = 'ferro_prototipo'
AND (le.pedido_id = sub.pedido_id OR le.presupuesto_id = sub.presupuesto_id)
)
", null, false);
return $builder;
}
public static function findDireccionesNewEnvio($ot_id, $searchVal = "")
{
$direcciones = [];
@ -126,7 +167,9 @@ class LogisticaService
->join('presupuestos pr', 'pr.id=presupuesto_direcciones.presupuesto_id')
->join('pedidos_linea pl', 'pl.presupuesto_id = pr.id')
->join('pedidos p', 'pl.pedido_id=p.id')
->where('p.id', $pedido_id);
->join('ordenes_trabajo ot', 'ot.pedido_id = p.id')
->where('ot.id', $ot_id)
->where("presupuesto_direcciones.is_ferro_prototipo", 0);
if ($searchVal != "") {
$dirs = $dirs->groupStart()
->Like("id", $searchVal)
@ -138,10 +181,13 @@ class LogisticaService
$unidades_en_direccion = $modelEnvioLineasModel->select('SUM(envios_lineas.unidades_envio) as unidades_enviadas,
envios_lineas.unidades_total')
->join('envios', 'envios.id = envios_lineas.envio_id')
->where('pedido_id', $pedido_id)
->join('pedidos_linea', 'pedidos_linea.pedido_id = envios_lineas.pedido_id')
->join('pedidos', 'pedidos.id = pedidos_linea.pedido_id')
->join('ordenes_trabajo', 'ordenes_trabajo.pedido_id = pedidos.id')
->where('ordenes_trabajo.id', $ot_id)
->where('envios.direccion', $direccion->direccion)
->where('envios.finalizado', 1)
->groupBy('pedido_id')->get()->getResult();
->groupBy('ordenes_trabajo.pedido_id')->get()->getResult();
if (count($unidades_en_direccion) == 0 || $unidades_en_direccion[0]->unidades_enviadas < $unidades_en_direccion[0]->unidades_total) {
array_push(
$direcciones,
@ -196,6 +242,7 @@ class LogisticaService
->join('pedidos p', 'p.id = pl.pedido_id')
->join('presupuestos pr', 'pr.id = pl.presupuesto_id')
->join('presupuesto_direcciones pd', 'pd.presupuesto_id = pr.id')
->where('pd.is_ferro_prototipo', 0)
->where('p.id', $pedido_id)
->whereIn('p.estado', ['finalizado', 'produccion'])
->where("TRIM(LOWER(pd.direccion)) = '$direccionNormalizada'", null, false)
@ -242,7 +289,7 @@ class LogisticaService
public static function generateEnvio($pedido_id, $direccion = null)
public static function generateEnvio($ot_id, $direccion = null)
{
$presupuestoDireccionesModel = model('App\Models\Presupuestos\PresupuestoDireccionesModel');
$direccionNormalizada = strtolower(trim($direccion));
@ -259,6 +306,7 @@ class LogisticaService
presupuesto_direcciones.pais_id,
presupuesto_direcciones.cantidad as cantidad_total,
presupuestos.cliente_id as cliente_id,
ordenes_trabajo.pedido_id as pedido_id,
(
presupuesto_direcciones.cantidad - IFNULL((
@ -275,7 +323,9 @@ class LogisticaService
->join('pedidos_linea', 'pedidos_linea.presupuesto_id = presupuesto_direcciones.presupuesto_id')
->join('pedidos', 'pedidos.id = pedidos_linea.pedido_id')
->join('presupuestos', 'pedidos_linea.presupuesto_id = presupuestos.id')
->where('pedidos.id', $pedido_id)
->join('ordenes_trabajo', 'ordenes_trabajo.pedido_id = pedidos.id')
->where('ordenes_trabajo.id', $ot_id)
->where('presupuesto_direcciones.is_ferro_prototipo', 0)
->like('presupuesto_direcciones.direccion', $direccion)
->groupBy('presupuesto_direcciones.id')
->first();
@ -311,7 +361,7 @@ class LogisticaService
$EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');
$EnvioLineasModel->save([
'envio_id' => $idEnvio,
'pedido_id' => $pedido_id,
'pedido_id' => $datosEnvio->pedido_id,
'unidades_envio' => $datosEnvio->cantidad,
'unidades_total' => $datosEnvio->cantidad_total,
'cajas' => 1,
@ -332,6 +382,96 @@ class LogisticaService
}
public static function generateEnvioFerro($ot_id)
{
$presupuestoDireccionesModel = model('App\Models\Presupuestos\PresupuestoDireccionesModel');
$datosEnvio = $presupuestoDireccionesModel
->select("
presupuestos.id as presupuesto_id,
presupuesto_direcciones.att,
presupuesto_direcciones.direccion,
presupuesto_direcciones.provincia as ciudad,
presupuesto_direcciones.cp,
presupuesto_direcciones.telefono,
presupuesto_direcciones.email,
presupuesto_direcciones.pais_id,
presupuesto_direcciones.cantidad as cantidad_total,
presupuestos.cliente_id as cliente_id,
ordenes_trabajo.pedido_id as pedido_id,
")
->join('pedidos_linea', 'pedidos_linea.presupuesto_id = presupuesto_direcciones.presupuesto_id')
->join('pedidos', 'pedidos.id = pedidos_linea.pedido_id')
->join('presupuestos', 'pedidos_linea.presupuesto_id = presupuestos.id')
->join('ordenes_trabajo', 'ordenes_trabajo.pedido_id = pedidos.id')
->where('ordenes_trabajo.id', $ot_id)
->where('presupuesto_direcciones.is_ferro_prototipo', 1)
->where("
NOT EXISTS (
SELECT 1
FROM envios e
INNER JOIN envios_lineas el ON el.envio_id = e.id
WHERE e.tipo_envio = 'ferro_prototipo'
AND (el.pedido_id = pedidos.id OR el.presupuesto_id = presupuestos.id)
)
", null, false) // <= Esta es la parte nueva, importante
->groupBy('presupuesto_direcciones.id')
->first();
// Validación si no hay datos o no quedan unidades
if (empty($datosEnvio)) {
return [
'status' => false,
'message' => lang('Logistica.errors.noAddresses')
];
}
// Crear envío
$EnvioModel = model('App\Models\Logistica\EnvioModel');
$EnvioModel->set([
'cliente_id' => $datosEnvio->cliente_id,
'att' => $datosEnvio->att,
'direccion' => $datosEnvio->direccion,
'ciudad' => $datosEnvio->ciudad,
'cp' => $datosEnvio->cp,
'telefono' => $datosEnvio->telefono,
'email' => $datosEnvio->email,
'pais_id' => $datosEnvio->pais_id,
'cantidad' => 1,
'cajas' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
'tipo_envio' => 'ferro_prototipo',
]);
$EnvioModel->insert();
$idEnvio = $EnvioModel->insertID();
// Crear línea de envío
$EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');
$EnvioLineasModel->save([
'envio_id' => $idEnvio,
'pedido_id' => $datosEnvio->pedido_id,
'unidades_envio' => 1,
'unidades_total' => 1,
'cajas' => 1,
'unidades_cajas' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id,
'presupuesto_id' => (int) $datosEnvio->presupuesto_id
]);
return [
'status' => true,
'data' => [
'id_envio' => $idEnvio,
],
];
}
public static function finalizarEnvio($envio_id, $finalizar_ot = false)
{
// hay que comprobar que para todas las lineas de envio de este envio
@ -383,24 +523,36 @@ class LogisticaService
$cantidad_enviada = $cantidad_enviada[0]->unidades_enviadas;
}
if ($cantidad_enviada + $linea->unidades_envio == $pedido->total_tirada) {
if ($envio->tipo_envio == 'ferro_prototipo') {
$otModel = model('App\Models\OrdenTrabajo\OrdenTrabajoModel');
$ot = $otModel->where('pedido_id', $linea->pedido_id)
->first();
$ps = (new ProductionService())->init($ot->id);
$ps->updateOrdenTrabajoDate([
"name" => "envio_at",
"envio_at" => date('Y-m-d H:i:s')
"name" => "ferro_en_cliente_at",
"ferro_en_cliente_at" => date('Y-m-d H:i:s')
]);
if ($finalizar_ot) {
$ps->updateOrdenTrabajo(
[
"estado" => 'F'
]
);
array_push($ots, $ot->id);
} else {
if ($cantidad_enviada + $linea->unidades_envio == $pedido->total_tirada) {
$otModel = model('App\Models\OrdenTrabajo\OrdenTrabajoModel');
$ot = $otModel->where('pedido_id', $linea->pedido_id)
->first();
$ps = (new ProductionService())->init($ot->id);
$ps->updateOrdenTrabajoDate([
"name" => "envio_at",
"envio_at" => date('Y-m-d H:i:s')
]);
if ($finalizar_ot) {
$ps->updateOrdenTrabajo(
[
"estado" => 'F'
]
);
array_push($ots, $ot->id);
}
}
}
}
$EnvioModel->update($envio_id, ['finalizado' => 1]);
@ -424,19 +576,19 @@ class LogisticaService
$data = [
"printer" => $printer->name,
"header" => [
"_FORMAT" => "E:PEDIDO.ZPL",
"_QUANTITY" => 1,
"_PRINBTERNAME" => $printer->name,
"_JOBNAME" => "LBL101"
],
"_FORMAT" => "E:PEDIDO.ZPL",
"_QUANTITY" => 1,
"_PRINBTERNAME" => $printer->name,
"_JOBNAME" => "LBL101"
],
];
foreach ($lineas as $linea) {
$data["labels"][] = [
"cliente" => $envio->cliente,
"titulo" => "[" . $linea->pedido_id . "] - " . $linea->titulo,
"titulo" => "[" . $linea->pedido_id . "] - " . $linea->titulo,
"cantidad" => $linea->unidades_envio,
"tirada" => $linea->unidades_total,
"tirada" => $linea->unidades_total,
"cajas" => $cajas,
"ean" => null,
"nombre" => $envio->att,
@ -449,15 +601,15 @@ class LogisticaService
$servicioImpresora = new ImpresoraEtiquetaService();
$xml = $servicioImpresora->createEtiqueta($data);
if($xml == null){
if ($xml == null) {
return [
'status' => false,
'message' => lang('Logistica.errors.noEtiquetas'),
];
}
$sk_environment = getenv('SK_ENVIRONMENT');
if($sk_environment == 'production'){
if ($sk_environment == 'production') {
$status = $servicioImpresora->sendToImpresoraEtiqueta("ETIQUETA", $xml, $printer);
if ($status) {
return [
@ -472,7 +624,7 @@ class LogisticaService
];
}
}else{
} else {
return [
'status' => true,
'message' => lang('Logistica.success.imprimirEtiquetas'),

View File

@ -18,6 +18,7 @@ use App\Entities\Produccion\OrdenTrabajoFileEntity;
use App\Entities\Produccion\OrdenTrabajoTareaEntity;
use App\Entities\Tarifas\Acabados\TarifaAcabadoEntity;
use App\Models\Configuracion\ConfigVariableModel;
use App\Models\Configuracion\FestivoModel;
use App\Models\Configuracion\MaquinaModel;
use App\Models\OrdenTrabajo\OrdenTrabajoFileModel;
use App\Models\OrdenTrabajo\OrdenTrabajoTareaProgressDate;
@ -56,6 +57,7 @@ class ProductionService extends BaseService
protected OrdenTrabajoUser $otUser;
protected OrdenTrabajoEntity $ot;
protected OrdenTrabajoFileModel $otFileModel;
protected FestivoModel $festivoModel;
protected OrdenTrabajoTareaProgressDate $otTareaProgressDate;
protected PedidoModel $pedidoModel;
protected UserModel $userModel;
@ -90,7 +92,7 @@ class ProductionService extends BaseService
* `tirada <= podValue`
* @var boolean
*/
protected bool $isPOD = false;
public bool $isPOD = false;
/**
* Indica si la orden de trabajo contiene gofrado
@ -98,7 +100,24 @@ class ProductionService extends BaseService
* @var boolean
*/
public bool $isGofrado = false; //* CHECK DONE
/**
* Indica si la orden de trabajo contiene plastificado
* Se usa para mostrar la fecha correspondiente en la vista
* @var boolean
*/
public bool $isPlastificado = false; //* CHECK DONE
/**
* Indica si la orden de trabajo contiene gofrado
* Se usa para mostrar la fecha correspondiente en la vista
* @var boolean
*/
public bool $isPlakene = false; //* CHECK DONE
/**
* Indica si la orden de trabajo contiene gofrado
* Se usa para mostrar la fecha correspondiente en la vista
* @var boolean
*/
public bool $isEstampado = false; //* CHECK DONE
/**
* Indica si la orden de trabajo contiene cosido
* Se usa para mostrar la fecha correspondiente en la vista y pliegos
@ -108,7 +127,7 @@ class ProductionService extends BaseService
/**
* Indica si la orden de trabajo contiene gofrado
* Se usa para mostrar la fecha correspondiente en la vista
* TODO Hay que implementar un boolean en `lg_tarifa_acabado` para identificar
* TODO Hay que implementar un boolean en `lg_tarifa_manipulado` para identificar
* @var boolean
*/
public bool $isGrapado = true; //TODO
@ -126,14 +145,7 @@ class ProductionService extends BaseService
* @var boolean
*/
public bool $isUVI = false; //* CHECK DONE
/**
* Indica si la orden de trabajo contiene plastificado
* Se usa para mostrar la fecha correspondiente en la vista
* TODO Hay que implementar un boolean en `lg_tarifa_acabado` para identificar
* DEFAULT true hasta implementacion
* @var boolean
*/
public bool $isPlastificado = true; //TODO
/**
* Indica si la orden de trabajo contiene cubierta
* Se usa para mostrar la fecha correspondiente en la vista
@ -182,6 +194,7 @@ class ProductionService extends BaseService
$this->otFileModel = model(OrdenTrabajoFileModel::class);
$this->pedidoModel = model(PedidoModel::class);
$this->otTareaProgressDate = model(OrdenTrabajoTareaProgressDate::class);
$this->festivoModel = model(FestivoModel::class);
$this->ordenTrabajoConfig = config('OrdenTrabajo');
$this->statusColor = $this->ordenTrabajoConfig->OT_COLORS["sin_imprimir"];
$this->configVariableModel = model(ConfigVariableModel::class);
@ -260,25 +273,19 @@ class ProductionService extends BaseService
/**
* Inserta las fechas del pedido asociado a la orden de trabajo en `orden_trabajo_tareas`
* Si el pedido es POD las fechas se insertan automaticamente usando `createDatesForPOD` y
* en base a las variables :
* - pod_impresion_dias_tras_confirmacion [fecha_impresion_at]
* - pod_encuadernacion_dias_tras_confirmacion [fecha_encuadernacion]
* - pod_entrega_real_dias_tras_confirmacion [fecha_impresion_at]
* - pod_embalaje_dias_tras_confirmacion [fecha_impresion_at]
*
* @param OrdenTrabajoEntity $ot
* @return integer|boolean|string ID
*/
protected function storeOrdenTrabajoDates(): int|bool|string
{
$fecha_encuadernado = Time::now()->addDays(2)->format("Y-m-d");
$fecha_entrega_real = Time::now()->addDays(5)->format("Y-m-d");
//$fecha_embalaje_at = Time::now()->addDays(4)->format("Y-m-d");
$data = [
"orden_trabajo_id" => $this->ot->id,
"fecha_encuadernado_at" => $fecha_encuadernado,
"fecha_entrega_real_at" => $fecha_entrega_real,
"fecha_impresion_at" => Time::now()->format("Y-m-d"),
//"embalaje_at" => $fecha_embalaje_at,
"fecha_entrega_externo" => $this->pedido->fecha_entrega_externo,
];
$otDateId = $this->otDate->insert($data);
$this->otDate->updateUserDateMap($this->ot->id, $data);
$otDateId = $this->otDate->insert(["orden_trabajo_id" => $this->ot->id]);
return $otDateId;
}
/**
@ -368,7 +375,7 @@ class ProductionService extends BaseService
$ot_tareas["maquina_id"] = $p_linea_maquina->id;
$ot_tareas["imposicion_id"] = null;
$ot_tareas["tiempo_estimado"] = $p_linea->horas_maquina * 3600;
$ot_tareas["tiempo_real"] = $p_linea->horas_maquina * 3600; //? Tiempo real se inserta manual?
$ot_tareas["tiempo_real"] = 0;
$insert_query_result = $this->otTarea->insert($ot_tareas);
$ot_tareas = [];
$this->storeTareaCorte($p_linea);
@ -392,7 +399,7 @@ class ProductionService extends BaseService
'maquina_id' => $this->defaultMaquinaCorte->id,
'orden' => $this->defaultMaquinaCorte->orden_planning,
'tiempo_estimado' => $pLinea->rotativa_tiempo_corte * 60,
'tiempo_real' => $pLinea->rotativa_tiempo_corte * 60,
'tiempo_real' => 0,
'is_corte' => true,
'tipo_corte' => "bobina",
]);
@ -840,6 +847,7 @@ class ProductionService extends BaseService
"preimpresiones" => $this->presupuesto->preimpresiones(),
"manipulados" => $this->presupuesto->manipulados(),
"encuadernaciones" => $this->presupuesto->encuadernaciones(),
"encuadernacionCode" => $this->getEncuadernacionCode(),
"linea_impresion" => $this->presupuesto->presupuestoLineaImpresion(),
"linea_cubierta" => $this->presupuesto->presupuestoLineaCubierta(),
"peso_unidad" => $logistica_data["peso_unidad"],
@ -850,7 +858,9 @@ class ProductionService extends BaseService
"colors" => $this->getPdfColors(),
"isPOD" => $this->isPOD,
"uvi" => $this->getUVI(),
"flags" => $this->getFlags(),
"tareaCosido" => $this->getTareaCosido(),
"plakene_tipo" => $this->plakene_tipo()
];
}
public function getImposicionTareaImpresion(): ?Imposicion
@ -1353,9 +1363,13 @@ class ProductionService extends BaseService
}
public function getTiempoProcesamientoHHMM(): ?string
{
$time_tareas_seconds = array_map(fn($q) => $q->tiempo_estimado ?? 0, $this->ot->tareas());
$seconds = array_sum($time_tareas_seconds);
return float_seconds_to_hhmm_string($seconds);
try {
$time_tareas_seconds = array_map(fn($q) => $q->tiempo_estimado ?? 0, $this->ot->tareas());
$seconds = array_sum($time_tareas_seconds);
return float_seconds_to_hhmm_string($seconds);
} catch (\Throwable $th) {
return '00:00';
}
}
public function getTiempoTareasImpresionHHMM(): string
{
@ -1373,7 +1387,7 @@ class ProductionService extends BaseService
$uvi = null;
$acabados = $this->presupuesto->acabados();
foreach ($acabados as $key => $acabado) {
if ($acabado->tarifa()->isUVI()) {
if ($acabado->tarifa()->uvi) {
$uvi = $acabado->tarifa();
}
}
@ -1489,8 +1503,11 @@ class ProductionService extends BaseService
{
$code = "";
$encuadernaciones = $this->presupuesto->encuadernaciones();
if (isset($encuadernaciones[0])) {
$code = $encuadernaciones[0]->tarifa()->code;
foreach ($encuadernaciones as $key => $value) {
$code = $value->tarifa()->code;
if ($code) {
break;
}
}
return $code;
}
@ -1525,58 +1542,68 @@ class ProductionService extends BaseService
}
public function getPapelImpresionBackgroundColor()
{
$papel = $this->presupuesto->presupuestoLineaImpresion()->papel_generico();
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['default'];
$papel_code = $papel->code_ot;
if ($papel_code) {
if (strpos($papel_code, "BCLOF")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['blanco'];
}
if (strpos($papel_code, "AH") && $papel->code == "OFF2") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['ahuesado'];
}
if (strpos($papel_code, "MARF")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['marfil'];
}
if (strpos($papel_code, "VOLAH")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['volumen_ahuesado'];
}
if ($papel_code == "EM") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['estucado_mate'];
}
if ($papel_code == "CGE") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['cartulina'];
}
}
if ($this->presupuesto->presupuestoLineaImpresion()) {
return $color;
$papel = $this->presupuesto->presupuestoLineaImpresion()->papel_generico();
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['default'];
$papel_code = $papel->code_ot;
if ($papel_code) {
if (strpos($papel_code, "BCLOF")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['blanco'];
}
if (strpos($papel_code, "AH") && $papel->code == "OFF2") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['ahuesado'];
}
if (strpos($papel_code, "MARF")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['marfil'];
}
if (strpos($papel_code, "VOLAH")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['volumen_ahuesado'];
}
if ($papel_code == "EM") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['estucado_mate'];
}
if ($papel_code == "CGE") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['cartulina'];
}
}
return $color;
} else {
return $this->ordenTrabajoConfig->OT_PAPEL_COLOR['blanco'];
}
}
public function getPapelImpresionCubiertaBackgroundColor()
{
$papel = $this->presupuesto->presupuestoLineaCubierta()->papel_generico();
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['default'];
$papel_code = $papel->code_ot;
if ($papel_code) {
if (strpos($papel_code, "BCLOF")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['blanco'];
}
if (strpos($papel_code, "AH") && $papel->code == "OFF2") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['ahuesado'];
}
if (strpos($papel_code, "MARF")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['marfil'];
}
if (strpos($papel_code, "VOLAH")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['volumen_ahuesado'];
}
if ($papel_code == "EM") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['estucado_mate'];
}
if ($papel_code == "CGE") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['cartulina'];
if ($this->presupuesto->presupuestoLineaCubierta()) {
$papel = $this->presupuesto->presupuestoLineaCubierta()->papel_generico();
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['default'];
$papel_code = $papel->code_ot;
if ($papel_code) {
if (strpos($papel_code, "BCLOF")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['blanco'];
}
if (strpos($papel_code, "AH") && $papel->code == "OFF2") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['ahuesado'];
}
if (strpos($papel_code, "MARF")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['marfil'];
}
if (strpos($papel_code, "VOLAH")) {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['volumen_ahuesado'];
}
if ($papel_code == "EM") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['estucado_mate'];
}
if ($papel_code == "CGE") {
$color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['cartulina'];
}
}
return $color;
} else {
return $this->ordenTrabajoConfig->OT_PAPEL_COLOR['blanco'];
}
return $color;
}
public function getPlastificadoColor()
{
@ -1585,21 +1612,10 @@ class ProductionService extends BaseService
foreach ($acabados as $key => $acabado) {
$tarifa_acabado = $acabado->tarifa();
if ($tarifa_acabado->code) {
$plastificado_code = $tarifa_acabado->code;
if ($plastificado_code == "BRIL") {
$color = $this->ordenTrabajoConfig->OT_PLASTIFICADO_COLOR['BRIL'];
}
if ($plastificado_code == "MATE") {
$color = $this->ordenTrabajoConfig->OT_PLASTIFICADO_COLOR['MATE'];
}
if ($plastificado_code == "ANTI") {
$color = $this->ordenTrabajoConfig->OT_PLASTIFICADO_COLOR['ANTIRAYADO'];
}
if ($plastificado_code == "SAND") {
$color = $this->ordenTrabajoConfig->OT_PLASTIFICADO_COLOR['SANDY'];
}
if ($plastificado_code == "GOF") {
$color = $this->ordenTrabajoConfig->OT_PLASTIFICADO_COLOR['GOFRADO'];
if ($tarifa_acabado->plastificado) {
if (isset($this->ordenTrabajoConfig->OT_PLASTIFICADO_COLOR[$tarifa_acabado->plastificado_tipo])) {
$color = $this->ordenTrabajoConfig->OT_PLASTIFICADO_COLOR[$tarifa_acabado->plastificado_tipo];
}
}
}
}
@ -1630,9 +1646,9 @@ class ProductionService extends BaseService
$this->color();
return [
"isGofrado" => $this->gofrado(),
"isEspiral" => $this->isEspiral,
"isEspiral" => $this->isEspiral, //TODO
"isUVI" => $this->uvi(),
"isPlastificado" => $this->isPlastificado,
"isPlastificado" => $this->plastificado(),
"isCubierta" => $this->cubierta(),
"isColor" => $this->isColor,
"isBN" => $this->isBN,
@ -1658,6 +1674,61 @@ class ProductionService extends BaseService
$this->isGofrado = $flag;
return $this->isGofrado;
}
public function plakene(): bool
{
$flag = false;
$acabados = $this->presupuesto->acabados();
foreach ($acabados as $key => $acabado) {
$tarifa_acabado = $acabado->tarifa();
if ($tarifa_acabado->plakene) {
$flag = true;
break;
}
}
$this->isPlakene = $flag;
return $this->isPlakene;
}
public function plakene_tipo(): ?string
{
$tipo = "";
$acabados = $this->presupuesto->acabados();
foreach ($acabados as $key => $acabado) {
$tarifa_acabado = $acabado->tarifa();
if ($tarifa_acabado->plakene) {
$tipo = $tarifa_acabado->plakene_tipo;
break;
}
}
return $tipo;
}
public function plastificado(): bool
{
$flag = false;
$acabados = $this->presupuesto->acabados();
foreach ($acabados as $key => $acabado) {
$tarifa_acabado = $acabado->tarifa();
if ($tarifa_acabado->plastificado) {
$flag = true;
break;
}
}
$this->isPlastificado = $flag;
return $this->isPlastificado;
}
public function estampado(): bool
{
$flag = false;
$acabados = $this->presupuesto->acabados();
foreach ($acabados as $key => $acabado) {
$tarifa_acabado = $acabado->tarifa();
if ($tarifa_acabado->estampado) {
$flag = true;
break;
}
}
$this->isEstampado = $flag;
return $this->isEstampado;
}
public function cosido(): bool
{
$flag = false;
@ -1755,7 +1826,7 @@ class ProductionService extends BaseService
->join("lg_maquinas", "lg_maquinas.id = orden_trabajo_tareas.maquina_id", "left")
->join("lg_papel_impresion", "lg_papel_impresion.id = presupuesto_linea.papel_impresion_id", "left")
->groupStart()
->orWhere('orden_trabajo_tareas.maquina_id', $maquina_id)
->orWhere('orden_trabajo_tareas.maquina_id', $maquina_id) //!TODO
->orWhere('presupuesto_linea.maquina_id', $maquina_id)
->groupEnd()
// ->where('pedidos.fecha_impresion IS NOT NULL', null, false)
@ -1783,4 +1854,70 @@ class ProductionService extends BaseService
}
return $tareaCosido;
}
public function createDatesForPOD(): array
{
$podDates = [
'fecha_encuadernado' => null,
'fecha_entrega_real' => null,
'fecha_embalaje' => null,
'fecha_impresion' => null,
];
try {
$impresionDays = $this->configVariableModel->getVariable('pod_impresion_dias_tras_confirmacion')->value;
$encuadernadoDays = $this->configVariableModel->getVariable('pod_encuadernacion_dias_tras_confirmacion')->value;
$entregaRealDays = $this->configVariableModel->getVariable('pod_entrega_real_dias_tras_confirmacion')->value;
$embalajeDays = $this->configVariableModel->getVariable('pod_embalaje_dias_tras_confirmacion')->value;
$totalDays = array_sum([$impresionDays, $encuadernadoDays, $entregaRealDays, $embalajeDays]);
$dates = $this->generateWorkdaysFromToday($totalDays);
for ($i = 0; $i < count($dates); $i++) {
if ($i == $impresionDays) {
$podDates['fecha_impresion'] = $dates[$i];
}
if ($i == $encuadernadoDays) {
$podDates['fecha_encuadernado'] = $dates[$i];
}
if ($i == $entregaRealDays) {
$podDates['fecha_entrega_real'] = $dates[$i];
}
if ($i == $embalajeDays) {
$podDates['fecha_embalaje'] = $dates[$i];
}
}
return $podDates;
} catch (\Throwable $th) {
return ["error" => $th->getMessage()];
}
}
/**
* Devuelve un array con la longitud `$count` con las fechas que corresponde con días laborales.
* Menos fines de semana y festivos.
*
* @param integer $count
* @return array <str,YYYY-MM-DD>
*/
public function generateWorkdaysFromToday(int $count): array
{
$current = Time::now();
$workdays = [];
while (count($workdays) < $count) {
$dayOfWeek = $current->format('N'); // 1 (Lunes) to 7 (Domingo)
if ($dayOfWeek < 6) { // Lunes a Viernes
$date = $current->format('Y-m-d 00:00:00');
if ($this->festivoModel->isFestivo($date) == false) {
$workdays[] = $date;
}
}
$current = $current->addDays(1);
}
return $workdays;
}
public function updatePodDates(): bool
{
$dates = $this->createDatesForPOD();
return $this->pedidoModel->update($this->pedido->id, $dates);
}
}

View File

@ -12,7 +12,7 @@
</div>
<div class="col-md-6 mb-2">
<p class="mb-0">Clicks</p>
<h4 class="mb-0" id="clicks-info"><?= $ot_tarea->click_tarea ?></h4>
<h4 class="mb-0" id="clicks-info"><?= $ot_tarea->click_end - $ot_tarea->click_init ?></h4>
</div>
</div>

View File

@ -0,0 +1,64 @@
<?= $this->include('themes/_commonPartialsBs/select2bs5') ?>
<?= $this->include('themes/_commonPartialsBs/datatables') ?>
<?= $this->include('themes/_commonPartialsBs/sweetalert') ?>
<?= $this->include('themes/_commonPartialsBs/_confirm2delete') ?>
<?= $this->extend('themes/vuexy/main/defaultlayout') ?>
<?= $this->section('content'); ?>
<div class="container-fluid h-100">
<div class="row">
<div class="col-md-12">
<div class="card card-info">
<div class="card-header">
<h3 class="card-title"><?= lang('Festivos.moduleTitle') ?></h3>
</div>
<!--//.card-header -->
<div class="card-body m-10 section-block" id="festivoCard">
<?= view('themes/_commonPartialsBs/_alertBoxes'); ?>
<div id="calendar"></div>
<!--//.card-footer -->
</div>
<!--//.card -->
</div>
<!--//.col -->
</div>
</div>
</div>
<!--//.row -->
<?= $this->endSection() ?>
<?= $this->section('css') ?>
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/formvalidation/dist/css/formValidation.min.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/notiflix/notiflix.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/spinkit/spinkit.css') ?>" />
<?= $this->endSection() ?>
<?= $this->section("additionalExternalJs") ?>
<script src="<?= site_url("themes/vuexy/vendor/libs/notiflix/notiflix.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/FormValidation.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/plugins/Bootstrap5.min.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/plugins/AutoFocus.min.js") ?>"></script>
<script src="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.js') ?>"></script>
<script src="<?= site_url('themes/vuexy/vendor/libs/fullcalendar/dist/index.global.min.js') ?>"></script>
<script src="<?= site_url('themes/vuexy/vendor/libs/fullcalendar/packages/core/locales-all.global.min.js') ?>"></script>
<script type="module" src="<?= site_url("/assets/js/safekat/pages/configuracion/festivo/index.js") ?>"></script>
<?= $this->endSection() ?>

View File

@ -0,0 +1,106 @@
<?= $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">
<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>
</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() ?>

View File

@ -10,6 +10,7 @@
<div class="card">
<div class="card-header">
<h4><?= $boxTitle ?>
<?= ($envioEntity->tipo_envio == 'ferro_prototipo') ? '<span class="badge text-bg-warning fw-lg">FERRO</span>':'' ?>
<?= ($envioEntity->finalizado == 0) ? '' : '<span class="badge text-bg-success fw-lg">FINALIZADO</span>' ?>
</h4>
</div>
@ -18,7 +19,6 @@
<?= view("themes/_commonPartialsBs/_alertBoxes") ?>
<input type="hidden" id="id" name="id" value="<?= $envioEntity->id ?>">
<input type="hidden" id="nextCaja" name="next_caja" value="<?= $envioEntity->nextCaja ?>">
<div class="accordion accordion-bordered">
<div class="card accordion-item active mb-5">
@ -114,7 +114,7 @@
</div>
</div>
<?php if ($envioEntity->finalizado == 0): ?>
<?php if ($envioEntity->finalizado == 0 && $envioEntity->tipo_envio=='estandar'): ?>
<div class="accordion accordion-bordered">
<div class="card accordion-item active mb-5">
<h4 class="accordion-header px-4 py-3">
@ -172,7 +172,7 @@
<i class="ti ti-select"></i>
</button>
</div>
<?php if ($envioEntity->finalizado == 0): ?>
<?php if ($envioEntity->finalizado == 0 && $envioEntity->tipo_envio=='estandar'): ?>
<div class="col-sm-2 px-3">
<button id="btnEliminarLineas" name="btnEliminarLineas" tabindex="1"
class="btn btn-danger w-100">
@ -336,6 +336,7 @@
<ti class="ti ti-check"></ti>
</button>
</div>
<?php if ($envioEntity->tipo_envio=='estandar'): ?>
<div class="col-sm-3 px-3">
<button id="finalizarEnvioYOTs" name="finalizar_envio_ots" tabindex="1"
class="btn btn-primary mt-4 w-100 btn-finalizar">
@ -343,6 +344,7 @@
<ti class="ti ti-checks"></ti>
</button>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>

View File

@ -1,97 +0,0 @@
<?= $this->include("themes/_commonPartialsBs/sweetalert") ?>
<?= $this->include('themes/_commonPartialsBs/datatables') ?>
<?= $this->extend('themes/vuexy/main/defaultlayout') ?>
<?= $this->section('content'); ?>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4><?= $boxTitle ?></h4>
</div>
<div class="card-body">
<?= view("themes/_commonPartialsBs/_alertBoxes") ?>
<div class="card accordion-item active mb-5">
<h4 class="accordion-header px-4 py-3">
<?= lang("Logistica.nuevoEnvio") ?>
</h4>
<div id="accordionNuevoEnvioTip" class="accordion-collapse collapse show">
<div class="accordion-body px-4 py-3">
<div class="row">
<div class="mb-1 col-sm-4">
<label for="buscadorPedidos" class="form-label">
<?= lang("Logistica.buscadorPedidosTitle") ?>
</label>
<input id="buscadorPedidos" name="buscador_pedidos" tabindex="1" maxlength="50"
class="form-control" value="">
</div>
</div>
</div>
</div>
</div>
<div class="card accordion-item active">
<h4 class="accordion-header px-4 py-3">
<?= lang("Logistica.listadoEnvios") ?>
</h4>
<div id="accordionListadoEnviosTip" class="accordion-collapse collapse show">
<div class="accordion-body px-4 py-3">
<div class="row">
<table id="tableOfEnvios" class="table table-striped table-hover w-100">
<thead>
<tr>
<th><?= lang('Logistica.idEnvio') ?? 'ID Envío' ?></th>
<th><?= lang('Logistica.numeroOts') ?? 'Nº OTs' ?></th>
<th><?= lang('Logistica.numeroLineas') ?? 'Nº Líneas' ?></th>
<th><?= lang('Logistica.att') ?? 'Att' ?></th>
<th><?= lang('Logistica.direccion') ?? 'Dirección' ?></th>
<th><?= lang('Logistica.ciudad') ?? 'Ciudad' ?></th>
<th><?= lang('Logistica.pais') ?? 'País' ?></th>
<th><?= lang('Logistica.cp') ?? 'CP' ?></th>
<th><?= lang('Logistica.email') ?? 'Email' ?></th>
<th><?= lang('Logistica.telefono') ?? 'Teléfono' ?></th>
<th><?= lang('Logistica.finalizado') ?? 'Finalizado' ?></th>
<th><?= lang('Logistica.acciones') ?? 'Acciones' ?></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="mt-3">
<button type="button" class="btn btn-secondary" id="btnImprimirEtiquetas"
onclick="window.location.href='<?= route_to('LogisticaPanel') ?>'">
<?= lang('Logistica.backToPanel') ?>
</button>
</div>
</div>
</div>
</div>
</div>
<?= $this->endSection() ?>
<?= $this->section('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/sweetalert2/sweetalert2.js') ?>"></script>
<script type="module" src="<?= site_url("assets/js/safekat/pages/logistica/envio.js") ?>"></script>
<?= $this->endSection() ?>

View File

@ -12,6 +12,8 @@
</div>
<div class="card-body">
<input type="hidden" id="tipo_envio" value="<?= $tipo_envio ?>" />
<?= view("themes/_commonPartialsBs/_alertBoxes") ?>
<div class="card accordion-item active mb-5">

View File

@ -17,7 +17,7 @@
<img src="<?= site_url("assets/img/logistica/envios.jpg") ?>" alt="Envíos">
<div><span><?= lang("Logistica.gestionEnvios"); ?></span></div>
</div>
<div class="item">
<div class="item" onclick="location.href='<?= route_to('gestionEnviosFerros') ?>'">
<img src="<?= site_url("assets/img/logistica/envios_ferros.png") ?>" alt="Envío de Ferros/Prototipos">
<div><span><?= lang("Logistica.envioFerros"); ?></span></div>
</div>

View File

@ -26,6 +26,9 @@ use Config\App;
<li class="nav-item">
<button type="button" class="nav-link" role="tab" id="navs-top-align-facturas-tab" data-bs-toggle="tab" data-bs-target="#navs-top-align-facturas"><?=lang('App.menu_facturas')?></button>
</li>
<li class="nav-item">
<button type="button" class="nav-link" role="tab" id="navs-top-align-ot-tab" data-bs-toggle="tab" data-bs-target="#navs-top-align-ots"><?=lang('Produccion.ots')?></button>
</li>
</ul>
<div class="tab-content" id="message-datatables-container">
@ -41,7 +44,9 @@ use Config\App;
</div>
<div class="tab-pane fade show" id="navs-top-align-facturas">
<?= view("themes/vuexy/components/tables/messages_table", ["id" => "tableFacturaMessages"]) ?>
</div>
<div class="tab-pane fade show" id="navs-top-align-ots">
<?= view("themes/vuexy/components/tables/messages_table", ["id" => "tableOtMessages"]) ?>
</div>
</div>
<!--//.card -->

View File

@ -39,6 +39,7 @@
<th class="lp-header"><?= lang('PresupuestosDirecciones.costePrecio') ?></th>
<th class="lp-header"><?= lang('Tarifaacabado.margen') ?></th>
<th class="lp-header">Pallets?</th>
<th class="lp-header">Ferro o Prototipo?</th>
<th style="min-width:120px !important;" class="lp-header"><?= lang('Basic.global.Action') ?></th>
</tr>
</thead>
@ -60,6 +61,7 @@
<button id="insertar_direccion" type="button" class="btn btn-secondary waves-effect waves-light float-start"><?= lang("Presupuestos.insertar")?></button>
</div>
</div>
</div> <!-- //.accordion-body -->
</div> <!-- //.accordion-collapse -->
</div> <!-- //.accordion-item -->

View File

@ -8,6 +8,15 @@
<div class="modal-body">
<div id='error-tarifa'></div>
<div class="mb-3" id="direccionFerroProto">
<label for="dirFerroProto" class="form-label">
Dirección Ferro o Prototipo
</label>
<input type="checkbox" id="dirFerroProto" class="form-check-input">
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_clientedAdd" class="form-label">
<?= lang('PresupuestosDirecciones.clientedAdd') ?>*

View File

@ -0,0 +1,63 @@
<?= $this->include('themes/_commonPartialsBs/select2bs5') ?>
<?= $this->include('themes/_commonPartialsBs/datatables') ?>
<?= $this->include('themes/_commonPartialsBs/sweetalert') ?>
<?= $this->include('themes/_commonPartialsBs/_confirm2delete') ?>
<?= $this->extend('themes/vuexy/main/defaultlayout') ?>
<?= $this->section('content'); ?>
<!--Content Body-->
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table class="table-maquinista table table-hover text-dark" style="width: 100%;">
<thead>
<tr>
<th><?= lang('ID') ?></th>
<th><?= lang('Users.firstName') ?></th>
<th><?= lang('Users.lastName') ?></th>
<th><?= lang('Users.email') ?></th>
<th class="text-nowrap"><?= lang('Basic.global.Action') ?></th>
</tr>
</thead>
<tbody>
<?php if (count($maquinistas) > 0): ?>
<?php foreach ($maquinistas as $key => $maquinista): ?>
<tr>
<td><?= $maquinista->id ?></td>
<td><?= $maquinista->first_name ?></td>
<td><?= $maquinista->last_name ?></td>
<td><?= $maquinista->getEmail() ?></td>
<td style="color: white;">
<a type="button" href="<?= route_to("maquinistaChangeUserSession", $maquinista->id) ?>" class="btn btn-lg btn-primary h-100 w-100">Mi turno</a>
</td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr class="text-center">
<td colspan="5">No hay usuarios para cambiar turno</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<?= $this->endSection() ?>
<?= $this->section('css') ?>
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/formvalidation/dist/css/formValidation.min.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/css/maquinista.css') ?>" />
<?= $this->endSection() ?>
<?= $this->section("additionalExternalJs") ?>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/FormValidation.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/plugins/Bootstrap5.min.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/plugins/AutoFocus.min.js") ?>"></script>
<?= $this->endSection() ?>

View File

@ -12,7 +12,7 @@
<div id="accordionOtTasksTip" class="accordion-collapse collapse show" data-bs-parent="#accordionOtTasks">
<div class="accordion-body">
<div class="card text-center">
<div class="card">
<div class="card-header">
<div class="nav-align-top">
<ul class="nav nav-pills" role="tablist">

View File

@ -110,6 +110,17 @@ $picture = "/assets/img/default-user.png";
<i class="ti ti-menu-2 ti-sm"></i>
</a>
</div>
<!-- CAMBIO DE USUARIO PARA MAQUINISTA -->
<?php if (auth()->user()->inGroup('maquina')): ?>
<div class="navbar-nav-left d-flex align-items-center" id="navbar-collapse">
<ul class="navbar-nav flex-row justify-content-start align-items-center ms-auto">
<li class="nav-item dropdown-shortcuts navbar-dropdown dropdown me-2 me-xl-0">
<a type="btn" href="<?= route_to('maquinistaUserChangeList') ?>" class="btn btn-outline-primary btn-sm w-100">Cambiar usuario</a>
</li>
</ul>
</div>
<?php endif; ?>
<div class="navbar-nav-right d-flex align-items-center" id="navbar-collapse">
<ul class="navbar-nav flex-row align-items-center ms-auto">

View File

@ -32,7 +32,7 @@
require "menus/maquinista_menu.php";
require "menus/importacion_menu.php";
require "menus/importadores_menu.php";
require "menus/catalogo_menu.php";

View File

@ -134,6 +134,13 @@ if (
</a>
</li>
<?php } ?>
<?php if (auth()->user()->inGroup('admin')) { ?>
<li class="menu-item">
<a href="<?= route_to('festivosList') ?>" class="menu-link">
<div> <?= lang("App.menu_config_holidays") ?></div>
</a>
</li>
<?php } ?>
</ul>
</li>
<?php } ?>

View File

@ -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 } ?>

View 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 } ?>

View File

@ -1,7 +1,7 @@
<table>
<tr class="encuadernacion">
<th >Encuadernacion</th>
<th class="cell-50"></th>
<th class="cell-50"><?=$presupuesto->solapas > 0 ? "Solapas" : ""?></th>
<th class="cell-50"></th>
<th class="cell-50"></th>
<th class="cell-50"></th>
@ -10,10 +10,13 @@
<th class="cell-50">Marcapáginas</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td></td>
<td><?= $encuadernacion->tarifa()->nombre ?></td>
<?php if ($presupuesto->solapas > 0): ?>
<td><?= "SI ($presupuesto->solapas_ancho mm.)" ?></td>
<?php else: ?>
<td></td>
<?php endif; ?>
<td></td>
<td></td>
<td></td>
@ -21,7 +24,6 @@
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>

View File

@ -1,30 +0,0 @@
<table>
<tr class="encuadernacion">
<th >Encuadernacion</th>
<th class="cell-50">Solapas</th>
<th class="cell-50"></th>
<th class="cell-50"></th>
<th class="cell-50"></th>
<th class="cell-50"></th>
<th class="cell-50">Retractilado</th>
<th class="cell-50">Marcapáginas</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td><?= $presupuesto->solapas ? "SI ($presupuesto->solapas_ancho mm.)" : "NO" ?></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>
</tr>
<?php endif; ?>
</table>

View File

@ -9,17 +9,15 @@
<th class="cell-50">Retractilado</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td></td>
<td></td>
<td></td>
<td><?= $encuadernacion->tarifa()->nombre ?></td>
<td></td>
<td></td>
<td><?= $flags['isPlakene'] ? "SI" : "NO" ?></td>
<td><?= $plakene_tipo ?? "" ?></td>
<td><?= $encuadernacion->proveedor() ? $encuadernacion->proveedor()->nombre : "" ?></td>
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>

View File

@ -3,25 +3,27 @@
<th>Encuadernacion</th>
<th class="cell-50">Pliegos</th>
<th class="cell-50">Pliegos</th>
<th class="cell-50"></th>
<th class="cell-50"><?=$presupuesto->solapas > 0 ? "Solapas" : ""?></th>
<th class="cell-50">Sobrecubierta</th>
<th class="cell-50">Guardas</th>
<th class="cell-50">Retractilado</th>
<th class="cell-50">Marcapáginas</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td><?=$tareaCosido->pliego_1." de ".$tareaCosido->pliego_1_total?></td>
<td><?=$tareaCosido->pliego_2." de ".$tareaCosido->pliego_2_total?></td>
<td></td>
<td><?= $encuadernacion->tarifa()->nombre ?></td>
<td><?= $tareaCosido->pliego_1 . " de " . $tareaCosido->pliego_1_total ?></td>
<td><?= $tareaCosido->pliego_2 . " de " . $tareaCosido->pliego_2_total ?></td>
<?php if ($presupuesto->solapas > 0): ?>
<td><?= "SI ($presupuesto->solapas_ancho mm.)" ?></td>
<?php else: ?>
<td>NO</td>
<?php endif; ?>
<td><?= $presupuesto->hasSobrecubierta() ? "SI" : "NO" ?></td>
<td><?= $presupuesto->guardas ? "SI" : "NO" ?></td>
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>

View File

@ -1,30 +0,0 @@
<table>
<tr class="encuadernacion">
<th>Encuadernacion</th>
<th class="cell-50">Pliegos</th>
<th class="cell-50">Pliegos</th>
<th class="cell-50">Solapas</th>
<th class="cell-50">Sobrecubierta</th>
<th class="cell-50">Guardas</th>
<th class="cell-50">Retractilado</th>
<th class="cell-50">Marcapáginas</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td><?=$tareaCosido->pliego_1." de ".$tareaCosido->pliego_1_total?></td>
<td><?=$tareaCosido->pliego_2." de ".$tareaCosido->pliego_2_total?></td>
<td><?= $presupuesto->solapas ? "SI ($presupuesto->solapas_ancho mm.)" : "NO" ?></td>
<td><?= $presupuesto->hasSobrecubierta() ? "SI" : "NO" ?></td>
<td><?= $presupuesto->guardas ? "SI" : "NO" ?></td>
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>
</tr>
<?php endif; ?>
</table>

View File

@ -1,7 +1,7 @@
<table>
<tr class="encuadernacion">
<th >Encuadernacion</th>
<th class="cell-50"></th>
<th class="cell-50"><?=$presupuesto->solapas > 0 ? "Solapas" : ""?></th>
<th class="cell-50"></th>
<th class="cell-50"></th>
<th class="cell-50">Sobrecubierta</th>
@ -10,10 +10,13 @@
<th class="cell-50">Marcapáginas</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td></td>
<td><?= $encuadernacion->tarifa()->nombre ?></td>
<?php if ($encuadernacion->solapas > 0): ?>
<td><?= "SI ($presupuesto->solapas_ancho mm.)" ?></td>
<?php else: ?>
<td></td>
<?php endif; ?>
<td></td>
<td></td>
<td><?= $presupuesto->hasSobrecubierta() ? "SI" : "NO" ?></td>
@ -21,7 +24,6 @@
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>

View File

@ -1,36 +0,0 @@
<table>
<tr>
<th class="encuadernacion">Encuadernacion</th>
<th class="cell-50">Pliegos</th>
<th class="cell-50">Pliegos</th>
<th class="cell-50">Guardas</th>
<th class="cell-50">Guardas Impresion</th>
<th class="cell-50">Cabezada</th>
<th class="cell-50">Lomo</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td><?=$tareaCosido->pliego_1." de ".$tareaCosido->pliego_1_total?></td>
<td><?=$tareaCosido->pliego_2." de ".$tareaCosido->pliego_2_total?></td>
<td></td>
<td></td>
<td>Color/NO</td>
<td>Recto/Redondo</td>
</tr>
<tr>
<td class="encuadernacion" colspan="1">Sobrecubierta</td>
<td style="color:red" colspan="2"><?= $linea_impresion->isSobreCubierta() ? "SI" : "NO" ?></td>
<td class="encuadernacion">Retractilado</td>
<td style="color:red"><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<td class="encuadernacion">Marcapáginas</td>
<td style="color:red"><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>
</tr>
<?php endif; ?>
</table>

View File

@ -0,0 +1,48 @@
<table>
<tr>
<th class="encuadernacion">Encuadernacion</th>
<th class="cell-50">Pliegos</th>
<th class="cell-50">Pliegos</th>
<th class="cell-50">Guardas</th>
<th class="cell-50">Guardas Impresion</th>
<th class="cell-50">Cabezada</th>
<th class="cell-50">Lomo</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<tr style="color: red;">
<td><?= $encuadernacion->tarifa()->nombre ?></td>
<?php if ($tareaCosido): ?>
<td><?= $tareaCosido->pliego_1 . " de " . $tareaCosido->pliego_1_total ?></td>
<td><?= $tareaCosido->pliego_2 . " de " . $tareaCosido->pliego_2_total ?></td>
<?php else: ?>
<td><?= "___de___" ?></td>
<td><?= "___de___" ?></td>
<?php endif; ?>
<!-- Guardas -->
<?php if ($presupuesto->presupuestoLineaGuarda()): ?>
<td><?= $presupuesto->presupuestoLineaGuarda()->papel_generico()?->code ?></td>
<td><?= $presupuesto->presupuestoLineaGuarda()->paginas_impresion > 0 ? "SI" : "NO" ?></td>
<?php else: ?>
<td>?</td>
<td><?= $presupuesto->presupuestoLineaGuarda()->paginas_impresion > 0 ? "SI" : "NO" ?>></td>
<?php endif; ?>
<!-- Cabezada -->
<td><?= $presupuesto->cabezada ? "COLOR" : "NO" ?></td>
<!-- Lomo -->
<td><?= $presupuesto->lomo_redondo ? "REDONDO" : "RECTO" ?></td>
</tr>
<tr>
<td class="encuadernacion" colspan="1">Sobrecubierta</td>
<td style="color:red" colspan="2"><?= $linea_impresion->isSobreCubierta() ? "SI" : "NO" ?></td>
<td class="encuadernacion">Retractilado</td>
<td style="color:red"><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<td class="encuadernacion">Marcapáginas</td>
<td style="color:red"><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>
</tr>
<?php endif; ?>
</table>

View File

@ -1,6 +1,6 @@
<table>
<tr class="encuadernacion">
<th >Encuadernacion</th>
<th>Encuadernacion</th>
<th class="cell-50">Guardas</th>
<th class="cell-50">Guardas Imp.</th>
<th class="cell-50">Cabezada</th>
@ -10,18 +10,27 @@
<th class="cell-50">Marcapáginas</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td><?= $encuadernacion->tarifa()->nombre ?></td>
<!-- Guardas -->
<?php if ($presupuesto->presupuestoLineaGuarda()): ?>
<td><?= $presupuesto->presupuestoLineaGuarda()->papel_generico()?->nombre ?></td>
<td><?= $presupuesto->presupuestoLineaGuarda()->paginas_impresion > 0 ? "SI" : "NO" ?>></td>
<?php else: ?>
<td>?</td>
<td><?= $presupuesto->presupuestoLineaGuarda()->paginas_impresion > 0 ? "SI" : "NO" ?>></td>
<?php endif; ?>
<!-- Cabezada -->
<td><?= $presupuesto->cabezada ? "COLOR" : "NO" ?></td>
<!-- Lomo -->
<td><?= $presupuesto->lomo_redondo ? "REDONDO" : "RECTO" ?></td>
<!-- Sobrecubierta -->
<td><?= $linea_impresion->isSobreCubierta() ? "SI" : "NO" ?></td>
<!-- Retractilado -->
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<!-- Marcapaginas -->
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>

View File

@ -1,7 +1,4 @@
<table>
<caption>
WIO
</caption>
<tr class="encuadernacion">
<th class="cell-50">Encuadernacion</th>
<th class="cell-50">Color</th>
@ -11,16 +8,14 @@
<th class="cell-50">Retractilado</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td></td>
<td></td>
<td></td>
<td><?= $encuadernacion->tarifa()->nombre ?></td>
<td></td>
<td><?= $flags['isPlakene'] ? "SI" : "NO" ?></td>
<td><?= $plakene_tipo ?? "" ?></td>
<td><?= $encuadernacion->proveedor() ? $encuadernacion->proveedor()->nombre : "" ?></td>
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>

View File

@ -1,7 +1,7 @@
<table>
<tr class="encuadernacion">
<th >Encuadernacion</th>
<th class="cell-50">Solapas</th>
<th class="cell-50"></th>
<th class="cell-50"></th>
<th class="cell-50"></th>
<th class="cell-50">Sobrecubierta</th>
@ -10,10 +10,9 @@
<th class="cell-50">Marcapáginas</th>
</tr>
<?php if (count($encuadernaciones) > 0): ?>
<?php foreach ($encuadernaciones as $key => $value): ?>
<tr style="color: red;">
<td><?= $value->tarifa()->nombre ?></td>
<td><?= $presupuesto->solapas ? "SI ($presupuesto->solapas_ancho mm.)" : "NO" ?></td>
<td><?= $encuadernacion->tarifa()->nombre ?></td>
<td></td>
<td></td>
<td></td>
<td><?= $presupuesto->hasSobrecubierta() ? "SI" : "NO" ?></td>
@ -21,7 +20,6 @@
<td><?= $presupuesto->retractilado ? "SI" : "NO" ?></td>
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr style="color: red;">
<td colspan="7">Sin encuadernación</td>

View File

@ -81,13 +81,13 @@ $settings = $session->get('settings');
<div class="col-3 h-100">
<div class="row px-2 d-flex flex justify-content-between align-items-center">
<div class="col-6 w-100 text-center">
<span id="fecha_encuadernado_at" style="color:<?= $colors["general"]["color"] ?>;"><strong><?= $pedido->fecha_encuadernado ? Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->format('d/m/Y') : "??" ?></strong></span>
<span id="fecha_encuadernado_at" style="color:<?= $colors["general"]["color"] ?>;"><strong><?= $pedido->fecha_encuadernado ? Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->format('d/m/Y') : "" ?></strong></span>
</div>
</div>
<div class="row px-2 mt-2 h-100">
<table class="h-100">
<table class="h-100 bg-white">
<tr>
<th>IN</th>
<th class="bg-white">IN</th>
<td class="t-cell bg-white"><?= $ubicacion ?></td>
</tr>
<tr>
@ -113,18 +113,18 @@ $settings = $session->get('settings');
<div class="col-5">
<div class="row">
<div class="col-12 w-50 text-center" style="background-color: <?= $colors["ot"]["bg"] ?>;color:<?= $colors["ot"]["color"] ?>;">
<strong><?= isset($encuadernaciones[0]) ? $encuadernaciones[0]->tarifa()->code ?? "?" : "?" ?></strong>
<strong><?= $encuadernacionCode ?></strong>
</div>
</div>
<div class="row h-75">
<div class="col-6 square text-center" style="background-color: <?= $colors["papel_interior"]["bg"] ?>;color:<?= $colors["papel_interior"]["color"] ?>;">
<?= $linea_impresion->papel_impresion()->papel_code_ot ?>
<?= $linea_impresion?->papel_impresion()->papel_code_ot ?>
</div>
<div class="col-6 square text-center <?= $linea_impresion->isColor() ? "cmyk" : "bn" ?>">
<?= $tiempo_impresion ?>
</div>
<div class="col-6 square text-center" style="background-color: <?= $colors["papel_cubierta"]["bg"] ?>;color:<?= $colors["papel_cubierta"]["color"] ?>;">
<?= $linea_cubierta->papel_impresion()->papel_code_ot ?>
<?= $linea_cubierta?->papel_impresion()->papel_code_ot ?>
</div>
<div class="col-6 square text-center" style="background-color: <?= $colors["plastificado"]["bg"] ?>;color:<?= $colors["plastificado"]["color"] ?>;">
<?= isset($acabados[0]) ? $acabados[0]->tarifa()->code : "" ?>
@ -156,10 +156,10 @@ $settings = $session->get('settings');
<div class="row">
<div class="col-8">
<table class="h-50">
<tr>
<tr>
<th>IDSK</th>
<td class="t-cell">
</td>
</tr>
<tr>
@ -267,80 +267,87 @@ $settings = $session->get('settings');
</div>
</div>
</div>
<div class="row mb-2">
<div class="section-title cubierta">IMP. CUBIERTA</div>
<div class="col-12">
<?php if ($linea_cubierta): ?>
<div class="row mb-2">
<div class="section-title cubierta">IMP. CUBIERTA</div>
<div class="col-12">
<table>
<tr>
<td rowspan="3" class="row-logo-impresion"><img src="<?= site_url($linea_cubierta->get_impresion_logo()) ?>" width="35px" height="35px"></td>
<th>Tintas</th>
<th>Ejemplares</th>
<th>Maquina</th>
<th>Marcapaginas</th>
<th>Tiempo</th>
</tr>
<tr>
<td><?= $linea_cubierta->tinta() ?></td>
<td><?= $presupuesto->tirada ?></td>
<td><strong><?= $linea_cubierta->maquina()->nombre ?></strong></td>
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
<td><?= float_seconds_to_hhmm_string($linea_cubierta->horas_maquina * 3600) ?></td>
</tr>
<tr>
<td colspan="1"><?= json_decode($linea_cubierta->formas)->maquina_ancho ?>x<?= json_decode($linea_cubierta->formas)->maquina_alto ?></td>
<td colspan="1"><?= $papel_formato->ancho ?>x<?= $papel_formato->alto ?></td>
<td colspan="2"><?= $linea_cubierta->papel_impresion ?></td>
<td colspan="2"><?= $linea_cubierta->papel_impresion()->gramaje . " " . "gr" ?></td>
<table>
<tr>
<td rowspan="3" class="row-logo-impresion"><img src="<?= site_url($linea_cubierta->get_impresion_logo()) ?>" width="35px" height="35px"></td>
<th>Tintas</th>
<th>Ejemplares</th>
<th>Maquina</th>
<th>Marcapaginas</th>
<th>Tiempo</th>
</tr>
<tr>
<td><?= $linea_cubierta->tinta() ?></td>
<td><?= $presupuesto->tirada ?></td>
<td><strong><?= $linea_cubierta->maquina()->nombre ?></strong></td>
<td><?= $presupuesto->marcapaginas ? "SI" : "NO" ?></td>
<td><?= float_seconds_to_hhmm_string($linea_cubierta->horas_maquina * 3600) ?></td>
</tr>
<tr>
<td colspan="1"><?= json_decode($linea_cubierta->formas)->maquina_ancho ?>x<?= json_decode($linea_cubierta->formas)->maquina_alto ?></td>
<td colspan="1"><?= $papel_formato->ancho ?>x<?= $papel_formato->alto ?></td>
<td colspan="2"><?= $linea_cubierta->papel_impresion ?></td>
<td colspan="2"><?= $linea_cubierta->papel_impresion()->gramaje . " " . "gr" ?></td>
</tr>
</table>
<div class="comments">
<div class="flex-row cubierta">Comentarios cubierta</div>
<div class="comment-content">
<p>
</p>
</tr>
</table>
<div class="comments">
<div class="flex-row cubierta">Comentarios cubierta</div>
<div class="comment-content">
<p>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<?php endif; ?>
<div class="row mb-2">
<div class="section-title encuadernacion">ENCUADERNACIÓN</div>
<div class="section-title encuadernacion">ACABADOS/ENCUADERNACIÓN</div>
<div class="col-12">
<div class="col-1 w-10 mb-2 text-center" style="background-color: <?= $colors["ot"]["bg"] ?>;color:<?= $colors["ot"]["color"] ?>;">
<span class="fs-bold"><?= isset($encuadernaciones[0]) ? $encuadernaciones[0]->tarifa()->code ?? "?" : "?" ?></span>
<span class="fs-bold"><?= $encuadernacionCode ?></span>
</div>
<table>
<tr>
<td class="w-10 encuadernacion">Plastificado</td>
<td><?= $acabados[0]->tarifa()->nombre ?></td>
<td class="encuadernacion bg-encuadernacion" style="width: 100px;">UVI</td>
<td style="color:red;width:100px" class="bg-encuadernacion"> <?= $uvi ? 'SI' : "NO" ?> </td>
<td class="encuadernacion bg-encuadernacion" style="width: 100px;">EXTERNO:</td>
<td class="bg-encuadernacion" style="width: 100px;"></td>
</tr>
<tr>
<td class="text-start" colspan="2">Meter datos de solapas y preparación guillotina</td>
<td></td>
<td></td>
<td class="t-header">CORTE PIE:</td>
<td></td>
</tr>
<?php foreach ($acabados as $key => $acabado): ?>
<tr>
<td class="w-10 encuadernacion">Plastificado</td>
<td><?= $acabado->tarifa()->nombre ?></td>
<td class="encuadernacion bg-encuadernacion" style="width: 100px;">UVI</td>
<td style="color:red;width:100px" class="bg-encuadernacion"> <?= $uvi ? 'SI' : "NO" ?> </td>
<td class="encuadernacion bg-encuadernacion" style="width: 100px;">EXTERNO:</td>
<td class="bg-encuadernacion" style="width: 100px;"><?= $acabado->proveedor() ? $acabado->proveedor()->nombre : "" ?></td>
</tr>
<tr>
<td class="text-start" colspan="2">Meter datos de solapas y preparación guillotina</td>
<td></td>
<td></td>
<td class="t-header">CORTE PIE:</td>
<td></td>
</tr>
<?php endforeach; ?>
</table>
<?php
$encuadernacion_code = isset($encuadernaciones[0]) ? $encuadernaciones[0]->tarifa()->code : null;
try {
if ($encuadernacion_code) {
echo view("/themes/vuexy/pdfs/encuadernados/$encuadernacion_code.php");
} else {
throw new Exception('No existe código de encuadernación.');
foreach ($encuadernaciones as $key => $encuadernacion) {
$encuadernacion_code = $encuadernacion->tarifa()->code;
try {
if ($encuadernacion_code) {
echo view("/themes/vuexy/pdfs/encuadernados/$encuadernacion_code.php", ["encuadernacion" => $encuadernacion]);
} else {
echo view("/themes/vuexy/pdfs/encuadernados/default.php", ["encuadernacion" => $encuadernacion]);
}
} catch (\Throwable $th) {
$error_message = $th->getMessage();
echo "<span style='color:red'>No se ha podido renderizar la tabla de encuadernación</span>";
// echo "<br><span style='color:red'>$error_message</span>";
}
} catch (\Throwable $th) {
$error_message = $th->getMessage();
echo "<span style='color:red'>No se ha podido renderizar la tabla de encuadernación</span>";
echo "<br><span style='color:red'>$error_message</span>";
}
?>
<?php if (count($encuadernaciones) > 0): ?>

View File

@ -0,0 +1,120 @@
import Ajax from '../components/ajax.js'
import { alertSuccess, alertError } from '../components/alerts/sweetAlert.js'
// Render calendar
class SafekatCalendar {
constructor(idElement) {
this.locale = $('meta[name=locale]').attr('content') ?? 'es';
this.calendarEl = document.getElementById(idElement);
this.calendar = null;
}
actionLoader(status = true) {
if (status) {
Notiflix.Block.circle('.section-block');
} else {
Notiflix.Block.remove('.section-block');
}
}
init() {
if (this.calendarEl) {
this.calendar = new FullCalendar.Calendar(this.calendarEl, {
locale: this.locale,
initialView: 'multiMonthYear',
multiMonthMaxColumns: 4,
contentHeight: '100vh',
editable: true,
dragScroll: true,
dayMaxEvents: 2,
dateClick: this.clickEvent.bind(this),
eventResizableFromStart: true,
customButtons: {
sidebarToggle: {
text: 'Sidebar'
}
},
});
this.calendar.render();
this.calendar.setOption('aspectRatio', 1.8);
}
}
renderFestivos() {
this.setEventFestivos()
}
async setEventFestivos() {
try {
let response = await this.getFestivos();
this.actionLoader(false)
if (response.data) {
let festivosEvent = response.data.map(this.parseToFullCalendarEvent)
this.addEvents(festivosEvent)
}
} catch (error) {
console.error(error)
} finally {
this.actionLoader(false)
}
}
removeEvents() {
this.calendar.getEvents().forEach(event => event.remove());
}
async clickEvent(info) {
try {
let response = await this.storeFestivo({ date: info.dateStr })
alertSuccess(response.message).fire()
this.renderFestivos()
} catch (error) {
console.error(error)
} finally {
this.actionLoader(false)
}
}
addEvents(events) {
events.forEach(event => {
this.calendar.addEvent(event)
});
}
parseToFullCalendarEvent(festivoEntity) {
let date = festivoEntity.date.split('-').reverse().join('/')
return {
id: festivoEntity.id,
title: '',
start: festivoEntity.date,
display: 'background',
color: 'red',
textColor: 'white'
}
}
getFestivos() {
this.actionLoader(true)
this.removeEvents()
return new Promise((resolve, reject) => {
let ajax = new Ajax('/configuracion/festivos/all', null, null, resolve, reject)
ajax.get()
})
}
storeFestivo(event) {
this.actionLoader(true)
return new Promise((resolve, reject) => {
let ajax = new Ajax('/configuracion/festivos', event, null, resolve, reject)
ajax.post()
})
}
deleteFestivo(id) {
return new Promise((resolve, reject) => {
let ajax = new Ajax('/configuracion/festivos/' + id, null, null, resolve, reject)
ajax.delete()
})
}
}
export default SafekatCalendar

View File

@ -7,6 +7,8 @@ class MessagesDatatable {
this.datatablePresupuestoMessageItem = this.item.find("#tablePresupuestoMessages")
this.datatablePedidoMessageItem = this.item.find("#tablePedidoMessages")
this.datatableFacturaMessageItem = this.item.find("#tableFacturaMessages")
this.datatableOtMessageItem = this.item.find("#tableOtMessages")
this.focusTable = this.datatableItem
this.columnDefs = [
]
@ -131,6 +133,25 @@ class MessagesDatatable {
columns: this.datatableColumns,
ajax: '/messages/datatable/factura'
});
this.datatableOtMessage = this.datatableOtMessageItem.DataTable({
processing: true,
order: [[1, 'desc']],
columnDefs : this.columnDefs,
orderCellsTop : true,
layout: {
topStart: 'pageLength',
topEnd: 'search',
bottomStart: 'info',
bottomEnd: 'paging'
},
serverSide: true,
pageLength: 10,
language: {
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
},
columns: this.datatableColumns,
ajax: '/messages/datatable/ots'
});
this.datatablePresupuestoMessageItem.on("keyup", ".datatable-message-filter", (event) => {
let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name"))
this.datatablePresupuestoMessage.column(columnIndex).search($(event.currentTarget).val()).draw()
@ -143,6 +164,10 @@ class MessagesDatatable {
let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name"))
this.datatableFacturaMessage.column(columnIndex).search($(event.currentTarget).val()).draw()
})
this.datatableOtMessageItem.on("keyup", ".datatable-message-filter", (event) => {
let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name"))
this.datatableFacturaMessage.column(columnIndex).search($(event.currentTarget).val()).draw()
})
}

View File

@ -0,0 +1,7 @@
import SafekatCalendar from "../../../components/SafekatCalendar.js"
$(() => {
let calendarFestivos = new SafekatCalendar('calendar');
calendarFestivos.init();
calendarFestivos.renderFestivos();
})

View File

@ -79,10 +79,14 @@ class MaquinistaTareaView {
}
handleUpdateClickInputSucess(response) {
popSuccessAlert(response.message)
this.updateContentClick(response.data.click_end - response.data.click_init)
}
handleUpdateClickInputError(error) {
popErrorAlert(error)
}
updateContentClick(clicks){
this.item.find('#clicks-info').empty().html(clicks)
}
handleDeleteTareaProgress() {
let ajax = new Ajax('/produccion/ordentrabajo/tarea/progress/' + this.tareaId,
null,
@ -194,6 +198,17 @@ class MaquinistaTareaView {
}
})
}
getTarea(tarea_id) {
return new Promise((resolve, reject) => {
let ajax = new Ajax(`/produccion/ordentrabajo/tarea/${tarea_id}`, null, null, (response) => {
resolve(response)
},
(error) => {
resolve(error)
})
ajax.get()
})
}
}

View File

@ -54,6 +54,10 @@ class MessagePage {
this.messageDatatable.datatableFacturaMessage.ajax.reload()
this.messageDatatable.focusTable = this.messageDatatable.datatableFacturaMessageItem
})
$("#navs-top-align-ot-tab").on("click",()=>{
this.messageDatatable.datatableOtMessage.ajax.reload()
this.messageDatatable.focusTable = this.messageDatatable.datatableOtMessageItem
})
}
openNewMessageModal() {

View File

@ -0,0 +1,301 @@
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']]
});
// 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;
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 result = await validarFila(rowData);
let checkboxHtml = '';
let actionBtnsHtml = '';
let notaHtml = '';
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>
`;
} 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>
`;
}
rows.push([checkboxHtml, ...rowData, notaHtml, 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 })
});
return await response.json();
} catch (error) {
console.error('Error validando fila', error);
return { apto: false, reason: 'Error conexión' };
}
}
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', async function () {
const $row = $(this).closest('tr');
const rowData = dataTable.row($row).data();
if (!rowData) return;
const fila = rowData.slice(1, 6); // solo datos de negocio
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?.replace('presupuestocliente', 'presupuestoadmin') ?? 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' }
});
}
});
// 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.',
icon: 'warning',
confirmButtonText: 'Aceptar',
buttonsStyling: true,
customClass: { confirmButton: 'btn btn-warning' }
});
return;
}
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?.replace('presupuestocliente', 'presupuestoadmin') ?? 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' }
});
});
});
});

View File

@ -4,11 +4,14 @@ import ClassSelect from '../../components/select2.js';
$(() => {
let otsFilter = '';
const tipo_envio = $('#tipo_envio').val();
const selectPedidos = new ClassSelect($('#buscadorPedidos'), '/logistica/selectForNewEnvio', "");
const selectPedidos = new ClassSelect($('#buscadorPedidos'), '/logistica/selectForNewEnvio', "", true, {
tipo_envio: () => $('#tipo_envio').val()
});
selectPedidos.init();
const selectDirecciones = new ClassSelect($('#selectDirecciones'), '/logistica/selectDireccionForEnvio', "", true, {
pedido_id: () => selectPedidos.getVal()
ot_id: () => selectPedidos.getVal()
});
selectDirecciones.init();
@ -19,7 +22,10 @@ $(() => {
})
selectPedidos.item.on('change', () => {
selectDirecciones.empty();
$('.select-direcciones').removeClass('d-none');
if(tipo_envio == 'ferro_prototipo')
$('.add-envio').removeClass('d-none');
else
$('.select-direcciones').removeClass('d-none');
})
selectDirecciones.item.on('select2:open', () => {
$('.add-envio').addClass('d-none');
@ -31,12 +37,24 @@ $(() => {
$('#btnAddEnvio').on('click', () => {
const pedido_id = selectPedidos.getVal();
const direccionSeleccionada = selectDirecciones.getText();
$.post('/logistica/generateEnvio', {
pedido_id: pedido_id,
direccion: direccionSeleccionada
}, function (response) {
let url = '';
let data = {};
if(tipo_envio == 'ferro_prototipo'){
url = '/logistica/generateEnvioFerro';
data = {
ot_id: selectPedidos.getVal()
};
}
else{
url = '/logistica/generateEnvio';
data = {
ot_id: selectPedidos.getVal(),
direccion: selectDirecciones.getText()
};
}
$.post(
url,
data, function (response) {
if (response.status) {
window.open(`${window.location.origin}/logistica/envio/${response.data.id_envio}`);
selectDirecciones.empty();
@ -51,7 +69,7 @@ $(() => {
});
})
const tableEnvios = $('#tableOfEnvios').DataTable({
processing: true,
serverSide: true,
@ -66,6 +84,7 @@ $(() => {
"url": "/logistica/datatableEnvios",
"data": function (d) {
d.otsFilter = otsFilter;
d.tipo_envio = $('#tipo_envio').val();
}
},
"columns": [

View File

@ -1,11 +1,11 @@
$(() => {
var opt = {
margin: 2,
filename: "PDF_OrdenTrabajo_" + $(".pdf-wrapper").data("id") + ".pdf",
image: { type: 'jpeg', quality: 1 },
html2canvas: { scale: 4 },
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }
};
let elementToPdf = $('body')[0]
html2pdf().set(opt).from(elementToPdf).save()
// var opt = {
// margin: 2,
// filename: "PDF_OrdenTrabajo_" + $(".pdf-wrapper").data("id") + ".pdf",
// image: { type: 'jpeg', quality: 1 },
// html2canvas: { scale: 4 },
// jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }
// };
// let elementToPdf = $('body')[0]
// html2pdf().set(opt).from(elementToPdf).save()
})

View File

@ -235,9 +235,35 @@ class DatosLibro {
if (this.ferro.prop('checked')) {
$(document).trigger('add-servicio-lineas', 'ferro');
$(document).trigger('update-presupuesto', {
update_lineas: false,
update_servicios: false,
update_envios: true,
update_resumen: false,
update_tiradas_alternativas: false
});
}
else {
$(document).trigger('remove-servicio-lineas', 'ferro');
if(!this.prototipo.prop('checked')){
const table = $('#tableOfDireccionesEnvio').DataTable();
const rows = table.rows().data();
for (let i = 0; i < rows.length; i++) {
const rowData = rows[i];
if (rowData.is_ferro_prototipo == 1) {
table.rows(i).remove();
table.draw();
break;
}
}
$(document).trigger('update-presupuesto', {
update_lineas: false,
update_servicios: false,
update_envios: true,
update_resumen: true,
update_tiradas_alternativas: true
});
}
}
}
@ -261,9 +287,35 @@ class DatosLibro {
if (this.prototipo.prop('checked')) {
$(document).trigger('add-servicio-lineas', 'prototipo');
$(document).trigger('update-presupuesto', {
update_lineas: false,
update_servicios: false,
update_envios: true,
update_resumen: false,
update_tiradas_alternativas: false
});
}
else {
$(document).trigger('remove-servicio-lineas', 'prototipo');
if(!this.ferro.prop('checked')){
const table = $('#tableOfDireccionesEnvio').DataTable();
const rows = table.rows().data();
for (let i = 0; i < rows.length; i++) {
const rowData = rows[i];
if (rowData.is_ferro_prototipo == 1) {
table.rows(i).remove();
table.draw();
break;
}
}
$(document).trigger('update-presupuesto', {
update_lineas: false,
update_servicios: false,
update_envios: true,
update_resumen: true,
update_tiradas_alternativas: true
});
}
}
}

View File

@ -71,6 +71,7 @@ class Envios {
},
{ 'data': 'margen', render: function (data, type, row) { return Math.round(data) } },
{ 'data': 'entregaPieCalle' },
{ 'data': 'is_ferro_prototipo' },
{
data: function (row, type, set, meta) {
return `
@ -87,7 +88,7 @@ class Envios {
orderable: false,
searchable: false,
// all columns
targets: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
targets: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
//targets: [$('#tableOfDireccionesEnvio').find("tr:first th").length - 1]
},
],
@ -97,7 +98,7 @@ class Envios {
drawCallback: function (settings) {
const boolCols = [15];
const boolCols = [15, 16];
for (let coln of boolCols) {
self.table.column(coln, { page: 'current' }).nodes().each(function (cell, i) {
cell.innerHTML = cell.innerHTML == '1' ? '<i class="ti ti-check"></i>' : '';
@ -164,6 +165,19 @@ class Envios {
$('#add_telefono').val(data.telefono)
$('#add_cantidad').val(data.cantidad)
$('#add_entregaPieCalle').prop('checked', data.entregaPieCalle == 1 ? true : false)
$('#dirFerroProto').prop('checked', data.is_ferro_prototipo == 1 ? true : false)
if (data.is_ferro_prototipo == 1) {
$('#add_cantidad').val(1);
$('#add_cantidad').attr('disabled', true);
$('#dirFerroProto').prop('disabled', true);
$('#direccionFerroProto').removeClass('d-none');
}
else {
$('#add_cantidad').attr('disabled', false);
$('#dirFerroProto').prop('disabled', false);
$('#direccionFerroProto').addClass('d-none');
}
self.direccionesClienteForm.setParams({ 'cliente_id': () => $("#clienteId").select2('data')[0].id });
self.direccionesClienteForm.init();
@ -220,6 +234,7 @@ class Envios {
let newAddDialog = $("#addressForm");
this.direccionesClienteForm.setParams({ 'cliente_id': () => $("#clienteId").select2('data')[0].id });
this.direccionesClienteForm.init();
let maximaCantidad = parseInt($('#tirada').val());
$("#add_cantidad").attr("max", maximaCantidad);;
$("#add_cantidad").val(maximaCantidad);
@ -228,16 +243,39 @@ class Envios {
})
let cantidad_total = 0;
let hasFerroPrototipo = false;
$('#tableOfDireccionesEnvio').DataTable().rows().every(function (rowIdx, tableLoop, rowLoop) {
let data = this.data();
cantidad_total += parseInt(data.cantidad);
if (data.is_ferro_prototipo == 0)
cantidad_total += parseInt(data.cantidad);
else
hasFerroPrototipo = true;
});
$('#add_cantidad').attr('max-value', parseInt($('#tirada').val()) - cantidad_total);
$('#add_cantidad').val(parseInt($('#tirada').val()) - cantidad_total);
const restante = parseInt($('#tirada').val()) - cantidad_total;
$('#add_cantidad').attr('max-value', restante);
$('#add_cantidad').val(restante > 0 ? restante : 0);
if (hasFerroPrototipo) {
$('#dirFerroProto').prop('checked', false);
$('#direccionFerroProto').addClass('d-none');
$('#add_cantidad').attr('disabled', false);
}
else {
if (restante == 0) {
$('#direccionFerroProto').removeClass('d-none');
$('#dirFerroProto').prop('checked', true);
$('#dirFerroProto').prop('disabled', true);
$('#add_cantidad').attr('disabled', true);
$('#add_cantidad').val(1);
}
}
newAddDialog.modal('show');
}
get_peso_libro() {
var peso_total_libro = 0.0
@ -277,11 +315,12 @@ class Envios {
margen: data.margen,
proveedor: data.proveedor,
proveedor_id: data.proveedor_id,
entregaPieCalle: data.entregaPieCalle
entregaPieCalle: data.entregaPieCalle,
is_ferro_prototipo: data.is_ferro_prototipo,
})
});
})
}
@ -379,11 +418,14 @@ class Envios {
'precio': datos_tarifa.precio.toFixed(2),
'margen': datos_tarifa.margen,
'entregaPieCalle': rowData.entregaPieCalle,
'is_ferro_prototipo': rowData.is_ferro_prototipo,
'actionBtns_direcciones': self.actionBtns_direcciones,
})
.draw();
self.check_unidades_enviadas(null,null);
$(document).trigger('update-presupuesto', {
update_lineas: false,
update_servicios: false,
@ -566,6 +608,7 @@ class Envios {
'precio': tarifa_final.precio,
'margen': tarifa_final.margen,
'entregaPieCalle': $('#add_entregaPieCalle').is(":checked") ? 1 : 0,
'is_ferro_prototipo': $('#dirFerroProto').is(":checked") ? 1 : 0,
'actionBtns_direcciones': `
<span class="edit-add"><a href="javascript:void(0);"><i class="ti ti-pencil ti-sm btn-edit-envio mx-2"></i></a></span>
<a href="javascript:void(0);"><i class="ti ti-trash ti-sm tiradas-alternativas btn-delete-envio mx-2"></i></a>
@ -673,8 +716,12 @@ class Envios {
}
let cantidad_total = 0
let hasFerroPrototipo = false
this.table.rows().every(function (rowIdx, tableLoop, rowLoop) {
cantidad_total += parseInt(this.data().cantidad)
if (this.data().is_ferro_prototipo == 0)
cantidad_total += parseInt(this.data().cantidad);
else
hasFerroPrototipo = true;
});
const tirada = parseInt($('#tirada').val());
@ -695,7 +742,11 @@ class Envios {
this.insertarEnvio.removeClass('d-none');
return false;
}
this.insertarEnvio.addClass('d-none');
if (($('#ferro').is(':checked') || $('#prototipo').is(':checked')) && !hasFerroPrototipo)
this.insertarEnvio.removeClass('d-none');
else
this.insertarEnvio.addClass('d-none');
$('#alert-envios').html(htmlString);
return true;
}

View File

@ -16,6 +16,128 @@ let direction = 'ltr';
if (isRtl) {
direction = 'rtl';
}
/**
* App Calendar Events
*/
let date = new Date();
let nextDay = new Date(new Date().getTime() + 24 * 60 * 60 * 1000);
// prettier-ignore
let nextMonth = date.getMonth() === 11 ? new Date(date.getFullYear() + 1, 0, 1) : new Date(date.getFullYear(), date.getMonth() + 1, 1);
// prettier-ignore
let prevMonth = date.getMonth() === 11 ? new Date(date.getFullYear() - 1, 0, 1) : new Date(date.getFullYear(), date.getMonth() - 1, 1);
let events = [
{
id: 1,
url: '',
title: 'Design Review',
start: date,
end: nextDay,
allDay: false,
extendedProps: {
calendar: 'Business'
}
},
{
id: 2,
url: '',
title: 'Meeting With Client',
start: new Date(date.getFullYear(), date.getMonth() + 1, -11),
end: new Date(date.getFullYear(), date.getMonth() + 1, -10),
allDay: true,
extendedProps: {
calendar: 'Business'
}
},
{
id: 3,
url: '',
title: 'Family Trip',
allDay: true,
start: new Date(date.getFullYear(), date.getMonth() + 1, -9),
end: new Date(date.getFullYear(), date.getMonth() + 1, -7),
extendedProps: {
calendar: 'Holiday'
}
},
{
id: 4,
url: '',
title: "Doctor's Appointment",
start: new Date(date.getFullYear(), date.getMonth() + 1, -11),
end: new Date(date.getFullYear(), date.getMonth() + 1, -10),
extendedProps: {
calendar: 'Personal'
}
},
{
id: 5,
url: '',
title: 'Dart Game?',
start: new Date(date.getFullYear(), date.getMonth() + 1, -13),
end: new Date(date.getFullYear(), date.getMonth() + 1, -12),
allDay: true,
extendedProps: {
calendar: 'ETC'
}
},
{
id: 6,
url: '',
title: 'Meditation',
start: new Date(date.getFullYear(), date.getMonth() + 1, -13),
end: new Date(date.getFullYear(), date.getMonth() + 1, -12),
allDay: true,
extendedProps: {
calendar: 'Personal'
}
},
{
id: 7,
url: '',
title: 'Dinner',
start: new Date(date.getFullYear(), date.getMonth() + 1, -13),
end: new Date(date.getFullYear(), date.getMonth() + 1, -12),
extendedProps: {
calendar: 'Family'
}
},
{
id: 8,
url: '',
title: 'Product Review',
start: new Date(date.getFullYear(), date.getMonth() + 1, -13),
end: new Date(date.getFullYear(), date.getMonth() + 1, -12),
allDay: true,
extendedProps: {
calendar: 'Business'
}
},
{
id: 9,
url: '',
title: 'Monthly Meeting',
start: nextMonth,
end: nextMonth,
allDay: true,
extendedProps: {
calendar: 'Business'
}
},
{
id: 10,
url: '',
title: 'Monthly Checkup',
start: prevMonth,
end: prevMonth,
allDay: true,
extendedProps: {
calendar: 'Personal'
}
}
];
document.addEventListener('DOMContentLoaded', function () {
(function () {

View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2021 Adam Shaw
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,73 @@
# FullCalendar
Full-sized drag & drop calendar in JavaScript
- [Project Website](https://fullcalendar.io/)
- [Documentation](https://fullcalendar.io/docs)
- [Changelog](CHANGELOG.md)
- [Support](https://fullcalendar.io/support)
- [License](LICENSE.md)
- [Roadmap](https://fullcalendar.io/roadmap)
Connectors:
- [React](https://github.com/fullcalendar/fullcalendar-react)
- [Angular](https://github.com/fullcalendar/fullcalendar-angular)
- [Vue 3](https://github.com/fullcalendar/fullcalendar-vue) |
[2](https://github.com/fullcalendar/fullcalendar-vue2)
## Bundle
The [FullCalendar Standard Bundle](bundle) is easier to install than individual plugins, though filesize will be larger. It works well with a CDN.
## Installation
Install the FullCalendar core package and any plugins you plan to use:
```sh
npm install @fullcalendar/core @fullcalendar/interaction @fullcalendar/daygrid
```
## Usage
Instantiate a Calendar with plugins and options:
```js
import { Calendar } from '@fullcalendar/core'
import interactionPlugin from '@fullcalendar/interaction'
import dayGridPlugin from '@fullcalendar/daygrid'
const calendarEl = document.getElementById('calendar')
const calendar = new Calendar(calendarEl, {
plugins: [
interactionPlugin,
dayGridPlugin
],
initialView: 'timeGridWeek',
editable: true,
events: [
{ title: 'Meeting', start: new Date() }
]
})
calendar.render()
```
## Development
You must install this repo with [PNPM](https://pnpm.io/):
```
pnpm install
```
Available scripts (via `pnpm run <script>`):
- `build` - build production-ready dist files
- `dev` - build & watch development dist files
- `test` - test headlessly
- `test:dev` - test interactively
- `lint`
- `clean`
[Info about contributing code &raquo;](CONTRIBUTING.md)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
},
initialDate: '2023-01-12',
navLinks: true, // can click day/week names to navigate views
businessHours: true, // display business hours
editable: true,
selectable: true,
events: [
{
title: 'Business Lunch',
start: '2023-01-03T13:00:00',
constraint: 'businessHours'
},
{
title: 'Meeting',
start: '2023-01-13T11:00:00',
constraint: 'availableForMeeting', // defined below
color: '#257e4a'
},
{
title: 'Conference',
start: '2023-01-18',
end: '2023-01-20'
},
{
title: 'Party',
start: '2023-01-29T20:00:00'
},
// areas where "Meeting" must be dropped
{
groupId: 'availableForMeeting',
start: '2023-01-11T10:00:00',
end: '2023-01-11T16:00:00',
display: 'background'
},
{
groupId: 'availableForMeeting',
start: '2023-01-13T10:00:00',
end: '2023-01-13T16:00:00',
display: 'background'
},
// red areas where no events can be dropped
{
start: '2023-01-24',
end: '2023-01-28',
overlap: false,
display: 'background',
color: '#ff9f89'
},
{
start: '2023-01-06',
end: '2023-01-08',
overlap: false,
display: 'background',
color: '#ff9f89'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prevYear,prev,next,nextYear today',
center: 'title',
right: 'dayGridMonth,dayGridWeek,dayGridDay'
},
initialDate: '2023-01-12',
navLinks: true, // can click day/week names to navigate views
editable: true,
dayMaxEvents: true, // allow "more" link when too many events
events: [
{
title: 'All Day Event',
start: '2023-01-01'
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var srcCalendarEl = document.getElementById('source-calendar');
var destCalendarEl = document.getElementById('destination-calendar');
var srcCalendar = new FullCalendar.Calendar(srcCalendarEl, {
editable: true,
initialDate: '2023-01-12',
events: [
{
title: 'event1',
start: '2023-01-11T10:00:00',
end: '2023-01-11T16:00:00'
},
{
title: 'event2',
start: '2023-01-13T10:00:00',
end: '2023-01-13T16:00:00'
}
],
eventLeave: function(info) {
console.log('event left!', info.event);
}
});
var destCalendar = new FullCalendar.Calendar(destCalendarEl, {
initialDate: '2023-01-12',
editable: true,
droppable: true, // will let it receive events!
eventReceive: function(info) {
console.log('event received!', info.event);
}
});
srcCalendar.render();
destCalendar.render();
});
</script>
<style>
body {
margin: 20px 0 0 20px;
font-size: 14px;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
}
#source-calendar,
#destination-calendar {
float: left;
width: 600px;
margin: 0 20px 20px 0;
}
</style>
</head>
<body>
<div id='source-calendar'></div>
<div id='destination-calendar'></div>
</body>
</html>

View File

@ -0,0 +1,149 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
/* initialize the external events
-----------------------------------------------------------------*/
var containerEl = document.getElementById('external-events-list');
new FullCalendar.Draggable(containerEl, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
return {
title: eventEl.innerText.trim()
}
}
});
//// the individual way to do it
// var containerEl = document.getElementById('external-events-list');
// var eventEls = Array.prototype.slice.call(
// containerEl.querySelectorAll('.fc-event')
// );
// eventEls.forEach(function(eventEl) {
// new FullCalendar.Draggable(eventEl, {
// eventData: {
// title: eventEl.innerText.trim(),
// }
// });
// });
/* initialize the calendar
-----------------------------------------------------------------*/
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
editable: true,
droppable: true, // this allows things to be dropped onto the calendar
drop: function(arg) {
// is the "remove after drop" checkbox checked?
if (document.getElementById('drop-remove').checked) {
// if so, remove the element from the "Draggable Events" list
arg.draggedEl.parentNode.removeChild(arg.draggedEl);
}
}
});
calendar.render();
});
</script>
<style>
body {
margin-top: 40px;
font-size: 14px;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
}
#external-events {
position: fixed;
left: 20px;
top: 20px;
width: 150px;
padding: 0 10px;
border: 1px solid #ccc;
background: #eee;
text-align: left;
}
#external-events h4 {
font-size: 16px;
margin-top: 0;
padding-top: 1em;
}
#external-events .fc-event {
margin: 3px 0;
cursor: move;
}
#external-events p {
margin: 1.5em 0;
font-size: 11px;
color: #666;
}
#external-events p input {
margin: 0;
vertical-align: middle;
}
#calendar-wrap {
margin-left: 200px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='wrap'>
<div id='external-events'>
<h4>Draggable Events</h4>
<div id='external-events-list'>
<div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
<div class='fc-event-main'>My Event 1</div>
</div>
<div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
<div class='fc-event-main'>My Event 2</div>
</div>
<div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
<div class='fc-event-main'>My Event 3</div>
</div>
<div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
<div class='fc-event-main'>My Event 4</div>
</div>
<div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
<div class='fc-event-main'>My Event 5</div>
</div>
</div>
<p>
<input type='checkbox' id='drop-remove' />
<label for='drop-remove'>remove after drop</label>
</p>
</div>
<div id='calendar-wrap'>
<div id='calendar'></div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,125 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
height: '100%',
expandRows: true,
slotMinTime: '08:00',
slotMaxTime: '20:00',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
initialView: 'dayGridMonth',
initialDate: '2023-01-12',
navLinks: true, // can click day/week names to navigate views
editable: true,
selectable: true,
nowIndicator: true,
dayMaxEvents: true, // allow "more" link when too many events
events: [
{
title: 'All Day Event',
start: '2023-01-01',
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
});
calendar.render();
});
</script>
<style>
html, body {
overflow: hidden; /* don't do scrollbars */
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.fc-header-toolbar {
/*
the calendar will be butting up against the edges,
but let's scoot in the header's buttons
*/
padding-top: 1em;
padding-left: 1em;
padding-right: 1em;
}
</style>
</head>
<body>
<div id='calendar-container'>
<div id='calendar'></div>
</div>
</body>
</html>

View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
height: 'auto',
// stickyHeaderDates: false, // for disabling
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'listMonth,listYear'
},
// customize the button names,
// otherwise they'd all just say "list"
views: {
listMonth: { buttonText: 'list month' },
listYear: { buttonText: 'list year' }
},
initialView: 'listYear',
initialDate: '2023-01-12',
navLinks: true, // can click day/week names to navigate views
editable: true,
events: [
{
title: 'repeating event 1',
daysOfWeek: [ 1, 2, 3 ],
duration: '00:30'
},
{
title: 'repeating event 2',
daysOfWeek: [ 1, 2, 3 ],
duration: '00:30'
},
{
title: 'repeating event 3',
daysOfWeek: [ 1, 2, 3 ],
duration: '00:30'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,114 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'listDay,listWeek'
},
// customize the button names,
// otherwise they'd all just say "list"
views: {
listDay: { buttonText: 'list day' },
listWeek: { buttonText: 'list week' }
},
initialView: 'listWeek',
initialDate: '2023-01-12',
navLinks: true, // can click day/week names to navigate views
editable: true,
dayMaxEvents: true, // allow "more" link when too many events
events: [
{
title: 'All Day Event',
start: '2023-01-01'
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialDate: '2023-01-12',
editable: true,
selectable: true,
businessHours: true,
dayMaxEvents: true, // allow "more" link when too many events
events: [
{
title: 'All Day Event',
start: '2023-01-01'
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'multiMonthYear,dayGridMonth,timeGridWeek'
},
initialView: 'multiMonthYear',
initialDate: '2023-01-12',
editable: true,
selectable: true,
dayMaxEvents: true, // allow "more" link when too many events
// multiMonthMaxColumns: 1, // guarantee single column
// showNonCurrentDates: true,
// fixedWeekCount: false,
// businessHours: true,
// weekends: false,
events: [
{
title: 'All Day Event',
start: '2023-01-01'
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1200px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridYear,dayGridMonth,timeGridWeek'
},
initialView: 'dayGridYear',
initialDate: '2023-01-12',
editable: true,
selectable: true,
dayMaxEvents: true, // allow "more" link when too many events
// businessHours: true,
// weekends: false,
events: [
{
title: 'All Day Event',
start: '2023-01-01'
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1200px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialDate: '2023-01-12',
initialView: 'timeGridWeek',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
height: 'auto',
navLinks: true, // can click day/week names to navigate views
editable: true,
selectable: true,
selectMirror: true,
nowIndicator: true,
events: [
{
title: 'All Day Event',
start: '2023-01-01',
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,123 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
initialDate: '2023-01-12',
navLinks: true, // can click day/week names to navigate views
selectable: true,
selectMirror: true,
select: function(arg) {
var title = prompt('Event Title:');
if (title) {
calendar.addEvent({
title: title,
start: arg.start,
end: arg.end,
allDay: arg.allDay
})
}
calendar.unselect()
},
eventClick: function(arg) {
if (confirm('Are you sure you want to delete this event?')) {
arg.event.remove()
}
},
editable: true,
dayMaxEvents: true, // allow "more" link when too many events
events: [
{
title: 'All Day Event',
start: '2023-01-01'
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,180 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<script src='../dist/index.global.js'></script>
<script>
/*
From https://github.com/fullcalendar/fullcalendar/issues/5026
*/
document.addEventListener('DOMContentLoaded', function() {
var calendarOptions = {
initialDate: '2023-01-12',
initialView: 'timeGridWeek',
nowIndicator: true,
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
navLinks: true, // can click day/week names to navigate views
editable: true,
selectable: true,
selectMirror: true,
dayMaxEvents: true, // allow "more" link when too many events
events: [
{
title: 'All Day Event',
start: '2023-01-01',
},
{
title: 'Long Event',
start: '2023-01-07',
end: '2023-01-10'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-09T16:00:00'
},
{
groupId: 999,
title: 'Repeating Event',
start: '2023-01-16T16:00:00'
},
{
title: 'Conference',
start: '2023-01-11',
end: '2023-01-13'
},
{
title: 'Meeting',
start: '2023-01-12T10:30:00',
end: '2023-01-12T12:30:00'
},
{
title: 'Lunch',
start: '2023-01-12T12:00:00'
},
{
title: 'Meeting',
start: '2023-01-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2023-01-12T17:30:00'
},
{
title: 'Dinner',
start: '2023-01-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2023-01-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2023-01-28'
}
]
};
var calendar = new FullCalendar.Calendar(document.getElementById('calendar'), calendarOptions);
calendar.render();
var calendar2 = new FullCalendar.Calendar(document.getElementById('calendar2'), calendarOptions);
calendar2.render();
/*
Modal
*/
var modal = document.querySelector('.modal');
var modalTrigger = document.querySelector('.modal-trigger');
var modalOverlay = document.querySelector('.modal-overlay');
modalTrigger.addEventListener('click', function() {
modal.classList.add('is-visible');
calendar2.updateSize();
});
modalOverlay.addEventListener('click', function() {
modal.classList.remove('is-visible');
});
});
</script>
<style>
body {
margin: 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
.modal {
display: none;
position: absolute;
z-index: 10000;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.modal.is-visible {
display: block;
}
.modal-overlay {
position: fixed;
z-index: 10;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: hsla(0, 0%, 0%, 0.5);
}
.modal-wrapper {
position: absolute;
z-index: 9999;
top: 6em;
left: 50%;
width: 600px;
margin-left: -16em;
background-color: #fff;
box-shadow: 0 0 1.5em hsla(0, 0%, 0%, 0.35);
}
.modal-content {
padding: 1em;
}
</style>
</head>
<body>
<button class='modal-trigger'>Show modal</button>
<div id='calendar'></div>
<div class='modal'>
<div class='modal-overlay'></div>
<div class='modal-wrapper'>
<div class='modal-content'>
<div id='calendar2'></div>
</div>
</div>
</div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More