From 5138681718b2b2463b663fea7e76c903d80ace6b Mon Sep 17 00:00:00 2001 From: amazuecos Date: Fri, 2 May 2025 07:56:28 +0200 Subject: [PATCH 001/127] feat/ot-datatable-news --- ci4/app/Config/OrdenTrabajo.php | 19 ++- ci4/app/Config/Routes.php | 4 + .../Controllers/Produccion/Ordentrabajo.php | 67 +++++++++- .../Produccion/OrdenTrabajoTareaEntity.php | 6 + .../Tarifas/Acabados/TarifaAcabadoEntity.php | 10 +- ci4/app/Language/es/Produccion.php | 43 ++++-- ci4/app/Services/ProductionService.php | 64 ++++++--- .../viewMaquinistaMaquinaTareas.php | 2 + .../vuexy/form/produccion/ot/otProgress.php | 8 +- .../form/produccion/viewOrdenTrabajoList.php | 28 +++- .../components/datatables/otDatatable.js | 122 +++++++++++++++++- .../maquinista/maquinistaTareaView.js | 24 +++- .../js/safekat/pages/produccion/index.js | 6 +- .../assets/js/safekat/pages/produccion/ot.js | 8 +- 14 files changed, 346 insertions(+), 65 deletions(-) diff --git a/ci4/app/Config/OrdenTrabajo.php b/ci4/app/Config/OrdenTrabajo.php index 4f8be2d4..0e63dd5a 100755 --- a/ci4/app/Config/OrdenTrabajo.php +++ b/ci4/app/Config/OrdenTrabajo.php @@ -12,14 +12,14 @@ class OrdenTrabajo extends BaseConfig "interior_bn_at" => "interior_bn_user_id", "interior_color_at" => "interior_color_user_id", "cubierta_at" => "cubierta_user_id", - "sobrecubierta_at" => "sobrecubierta_user_id", //TODO - "guarda_at" => "guarda_user_id", //TODO + "sobrecubierta_at" => "sobrecubierta_user_id", + "guarda_at" => "guarda_user_id", //ACABADO "plastificado_at" => "plastificado_user_id", - "plakene_at" => "plakene_user_id", //TODO + "plakene_at" => "plakene_user_id", "retractilado_at" => "retractilado_user_id", - "estampado_at" => "estampado_user_id", //TODO - "uvi_at" => "uvi_user_id", //TODO + "estampado_at" => "estampado_user_id", + "uvi_at" => "uvi_user_id", "encuadernacion_at" => "encuadernacion_user_id", "corte_at" => "corte_user_id", "preparacion_interiores_at" => "preparacion_interior_user_id", @@ -121,7 +121,14 @@ class OrdenTrabajo extends BaseConfig "default" => ["bg" => "white", "color" => "black"], ]; - + public array $OT_TAREA_STATUS_COLOR = [ + "P" => '#FFD63A', + "F" => '#67AE6E', + "S" => '#EB5B00', + "I" => '#3A59D1', + "E" => '#FF0B55', + "D" => '#FFA725', + ]; public function __construct() { diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 352a871e..fc2e1373 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -751,6 +751,10 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func $routes->get('datatable_pendientes', 'Ordentrabajo::datatable_pendientes'); $routes->get('datatable_ferro_pendiente', 'Ordentrabajo::datatable_ferro_pendiente'); $routes->get('datatable_ferro_ok', 'Ordentrabajo::datatable_ferro_ok'); + $routes->get('datatable_news', 'Ordentrabajo::datatable_news'); + $routes->get('datatable_prod', 'Ordentrabajo::datatable_prod'); + $routes->get('datatable_waiting', 'Ordentrabajo::datatable_waiting'); + $routes->get('datatable_revision_com', 'Ordentrabajo::datatable_revision_com'); $routes->get('tareas/datatable/(:num)', 'Ordentrabajo::tareas_datatable/$1', ['as' => 'datatableTareasOrdenTrabajo']); $routes->get("tarea/progress/(:num)", "Ordentrabajo::get_orden_trabajo_progress_date/$1"); $routes->get('tarea/(:num)', 'Ordentrabajo::find_tarea/$1'); diff --git a/ci4/app/Controllers/Produccion/Ordentrabajo.php b/ci4/app/Controllers/Produccion/Ordentrabajo.php index 413bb991..9d244726 100755 --- a/ci4/app/Controllers/Produccion/Ordentrabajo.php +++ b/ci4/app/Controllers/Produccion/Ordentrabajo.php @@ -283,6 +283,62 @@ class Ordentrabajo extends BaseController ->add("action", fn($q) => $q->id) ->toJson(true); } + public function datatable_news() + { + $logo = config(LogoImpresion::class); + + $q = $this->otModel->getDatatableQuery(); + 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()]) + ->edit( + "fecha_encuadernado_at", + fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" + ) + ->add("action", fn($q) => $q->id) + ->toJson(true); + } + public function datatable_prod() + { + $logo = config(LogoImpresion::class); + + $q = $this->otModel->getDatatableQuery()->where('presupuestos.ferro',1)->where("ferro_ok_at is NOT NULL", NULL, FALSE); + 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()]) + ->edit( + "fecha_encuadernado_at", + fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" + ) + ->add("action", fn($q) => $q->id) + ->toJson(true); + } + public function datatable_waiting() + { + $logo = config(LogoImpresion::class); + + $q = $this->otModel->getDatatableQuery()->where('ordenes_trabajo.is_pedido_espera',1); + 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()]) + ->edit( + "fecha_encuadernado_at", + fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" + ) + ->add("action", fn($q) => $q->id) + ->toJson(true); + } + public function datatable_revision_com() + { + $logo = config(LogoImpresion::class); + + $q = $this->otModel->getDatatableQuery()->where('presupuestos.ferro',1)->where("ferro_ok_at is NOT NULL", NULL, FALSE); + 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()]) + ->edit( + "fecha_encuadernado_at", + fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" + ) + ->add("action", fn($q) => $q->id) + ->toJson(true); + } public function papel_gramaje_datatable() { @@ -585,8 +641,15 @@ class Ordentrabajo extends BaseController $validated = $this->validation->run($bodyData, "orden_trabajo_tarea_progress_date"); // return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "data" => $this->validation->getValidated(),"errors" => $this->validation->getErrors()]); if ($validated) { - $r = $this->produccionService->storeOrdenTrabajoTareaProgressDate($this->validation->getValidated()); - return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $bodyData]); + $validatedData = $this->validation->getValidated(); + $r = $this->produccionService->storeOrdenTrabajoTareaProgressDate($validatedData); + $otTareaEntity = $this->otTarea->find($validatedData['ot_tarea_id']); + $data = [ + "tiempo_trabajado" => float_seconds_to_hhmm_string($otTareaEntity->tiempo_trabajado()), + "tarea" => $otTareaEntity, + "estado" => $validatedData['estado'], + ]; + return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $data]); } else { return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400); } diff --git a/ci4/app/Entities/Produccion/OrdenTrabajoTareaEntity.php b/ci4/app/Entities/Produccion/OrdenTrabajoTareaEntity.php index 1d32be82..3dcf518e 100755 --- a/ci4/app/Entities/Produccion/OrdenTrabajoTareaEntity.php +++ b/ci4/app/Entities/Produccion/OrdenTrabajoTareaEntity.php @@ -178,6 +178,12 @@ class OrdenTrabajoTareaEntity extends Entity $m = model(OrdenTrabajoTareaProgressDate::class); return $m->where('ot_tarea_id', $this->attributes["id"])->findAll() ?? []; } + public function lastState() : ?OrdenTrabajoTareaProgressDateEntity + { + $m = model(OrdenTrabajoTareaProgressDate::class); + $progressDates = $m->where('ot_tarea_id', $this->attributes["id"])->orderBy('action_at', 'DESC')->first(); + return $progressDates; + } public function tiempo_trabajado() { $dates = $this->progress_dates(); diff --git a/ci4/app/Entities/Tarifas/Acabados/TarifaAcabadoEntity.php b/ci4/app/Entities/Tarifas/Acabados/TarifaAcabadoEntity.php index 30d846b5..1af0fde3 100755 --- a/ci4/app/Entities/Tarifas/Acabados/TarifaAcabadoEntity.php +++ b/ci4/app/Entities/Tarifas/Acabados/TarifaAcabadoEntity.php @@ -24,11 +24,11 @@ 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' => null, + 'plakene' => null, + 'rectractilado' => null, + 'estampado' => null, + 'uvi' => null, 'plastificado_tipo' => null, 'plakene_tipo' => null, 'rectractilado_tipo' => null, diff --git a/ci4/app/Language/es/Produccion.php b/ci4/app/Language/es/Produccion.php index ee18d7b6..6d97b6fe 100755 --- a/ci4/app/Language/es/Produccion.php +++ b/ci4/app/Language/es/Produccion.php @@ -1,15 +1,25 @@ [ + 'finalizadas' => 'Finalizadas', + 'pendientes' => 'Pendientes', + 'pendientes_ferro' => 'Ferro pendiente', + 'ferro_ok' => 'Ferro/Prototipo OK', + 'news' => 'Nuevas', + 'waiting' => 'En espera', + 'revision_com' => 'Revisión comercial', + 'prod' => 'Producción' + ], "datatable" => [ - "pedido_id"=> "Pedido ID", - "fecha_encuadernacion"=> "Fecha encuadernación", - "fecha_impresion"=> "Fecha impresión", - "cliente"=> "Cliente", - "titulo"=> "Título", - "ubicacion"=> "Ubicación", - "tirada"=> "Tirada", - "impresion"=> "Impresión", + "pedido_id" => "Pedido ID", + "fecha_encuadernacion" => "Fecha encuadernación", + "fecha_impresion" => "Fecha impresión", + "cliente" => "Cliente", + "titulo" => "Título", + "ubicacion" => "Ubicación", + "tirada" => "Tirada", + "impresion" => "Impresión", "fecha_entrega_at" => "Fecha entrega prevista", "maquina" => "Máquina", "ancho" => "Ancho", @@ -31,8 +41,6 @@ return [ "pliegos" => "Pliegos", "pliegos_libro" => "Pliegos", "fecha" => "fecha" - - ], "task" => [ "order" => "Orden", @@ -116,7 +124,7 @@ return [ "pre_solapa" => "Revisión solapa", "pre_codbarras" => "Revisión código barras", "pre_imposicion" => "Revisión imposición", - + "iniciada" => "Iniciada", "finalizada" => "Finalizada", "error" => "Error", @@ -128,7 +136,7 @@ return [ "attr_not_exist" => "El atributo {0,string} no pertenece al modelo Pedido" ], - + "progress_ferro" => "Ferro", "progress_preimpresion" => "Preimpresión", "progress_logistica" => "Logística", @@ -139,6 +147,7 @@ return [ "maquinas" => "Máquinas", "tareas_hoy" => "Tareas para HOY", "tareas_all" => "Todas", + "tareas_delay" => "Aplazadas", "play_tarea" => "Continuar", "play_pause" => "Pausar", "play_stop" => "Aplazar", @@ -146,6 +155,14 @@ return [ "cancel" => "Cancelar", ], + 'tarea_estados' => [ + 'P' => 'Pendiente', + 'I' => 'Iniciada', + 'F' => 'Finalizada', + 'S' => 'Pausada', + 'D' => 'Aplazada', + 'E' => 'Error' + ], 'duplicate_estado_tarea_progress' => "Último estado de la tarea repetido", 'task_already_finished' => "La tarea se ha marcado como finalizada.", 'print_label' => "Imprimir etiqueta", @@ -158,4 +175,4 @@ return [ "comentariosEncuadernacion" => "Comentarios encuadernación", "comentariosLogistica" => "Comentarios logística", "info_solapa_guillotina" => "Datos solapa y preparación guillotina", -]; \ No newline at end of file +]; diff --git a/ci4/app/Services/ProductionService.php b/ci4/app/Services/ProductionService.php index de5c7dfa..4add157d 100755 --- a/ci4/app/Services/ProductionService.php +++ b/ci4/app/Services/ProductionService.php @@ -110,6 +110,12 @@ class ProductionService extends BaseService * @var boolean */ public bool $isPlastificado = false; //* CHECK DONE + /** + * Indica si la orden de trabajo contiene retractilado + * Se usa para mostrar la fecha correspondiente en la vista + * @var boolean + */ + public bool $isRetractilado = false; //* CHECK DONE /** * Indica si la orden de trabajo contiene gofrado * Se usa para mostrar la fecha correspondiente en la vista @@ -273,6 +279,10 @@ class ProductionService extends BaseService $this->storeOrdenTrabajoUsers(); $this->storeOrdenTrabajoDates(); $this->storeAllTareas(); + try { + $this->updatePodDates(); + } catch (\Throwable $th) { + } $this->updatePedidoEspera(); return $this->ot; } @@ -844,6 +854,7 @@ class ProductionService extends BaseService "tareas_preimpresion" => $this->tareas_preimpresion(), "tareas_impresion" => $this->tareas_impresion(), "tiempo_procesamiento" => $this->getTiempoProcesamientoHHMM(), + "tiempo_total" => $this->getTiempoTotalTareas(), "statusColor" => $this->getOtColorStatus(), "tareaCosido" => $this->getTareaCosido(), ]; @@ -989,8 +1000,8 @@ class ProductionService extends BaseService throw new Exception(lang('Produccion.task_already_finished')); } } - if(isset($data['estado'])){ - if($data['estado'] == 'F'){ + if (isset($data['estado'])) { + if ($data['estado'] == 'F') { $tareaEntity = $this->otTarea->find($data['ot_tarea_id']); $this->init($tareaEntity->orden_trabajo_id); $dateName = $this->getOrdenTrabajoTareaDate($tareaEntity); @@ -1015,11 +1026,11 @@ class ProductionService extends BaseService $data["action_at"] = Time::now()->format('Y-m-d H:i:s'); $data["action_user_id"] = auth()->user()->id; $status = $this->otTareaProgressDate->where('ot_tarea_id', $orden_trabajo_tarea_id)->delete(); - if($status){ - $tareaEntity = $this->otTarea->find($orden_trabajo_tarea_id); - $this->init($tareaEntity->orden_trabajo_id); - $dateName = $this->getOrdenTrabajoTareaDate($tareaEntity); - $this->emptyOrdenTrabajoDate($this->ot->id,$dateName); + if ($status) { + $tareaEntity = $this->otTarea->find($orden_trabajo_tarea_id); + $this->init($tareaEntity->orden_trabajo_id); + $dateName = $this->getOrdenTrabajoTareaDate($tareaEntity); + $this->emptyOrdenTrabajoDate($this->ot->id, $dateName); } if ($status) { $response = $this->storeOrdenTrabajoTareaProgressDate($data); @@ -1409,14 +1420,33 @@ class ProductionService extends BaseService } public function getTiempoTareasImpresionHHMM(): string { - $tareas_impresion = $this->ot->tareas_impresion(); - $tiempo_seconds = 0; - foreach ($tareas_impresion as $key => $tarea) { - if ($tarea->is_corte == false) { - $tiempo_seconds += $tarea->tiempo_estimado; + try { + $tareas_impresion = $this->ot->tareas_impresion(); + $tiempo_seconds = 0; + foreach ($tareas_impresion as $key => $tarea) { + if ($tarea->is_corte == false) { + $tiempo_seconds += $tarea->tiempo_estimado; + } } + return float_seconds_to_hhmm_string($tiempo_seconds); + } catch (\Throwable $th) { + return '00:00'; + } + } + public function getTiempoTotalTareas(): string + { + try { + $tareas = $this->ot->tareas(); + $tiempo_seconds = 0; + foreach ($tareas as $key => $tarea) { + if ($tarea->tiempo_real) { + $tiempo_seconds += $tarea->tiempo_real; + } + } + return float_seconds_to_hhmm_string($tiempo_seconds); + } catch (\Throwable $th) { + return '00:00'; } - return float_seconds_to_hhmm_string($tiempo_seconds); } public function getUVI(): ?TarifaAcabadoEntity { @@ -1735,13 +1765,13 @@ class ProductionService extends BaseService $acabados = $this->presupuesto->acabados(); foreach ($acabados as $key => $acabado) { $tarifa_acabado = $acabado->tarifa(); - if ($tarifa_acabado->retractilado) { + if ($tarifa_acabado->rectractilado) { $flag = true; break; } } - $this->isPlakene = $flag; - return $this->isPlakene; + $this->isRetractilado = $flag; + return $this->isRetractilado; } public function plakene_tipo(): ?string { @@ -1891,7 +1921,7 @@ class ProductionService extends BaseService ) ->join("pedidos", "pedidos.id = ordenes_trabajo.pedido_id", "right") ->join("lg_maquinas", "lg_maquinas.id = orden_trabajo_tareas.maquina_id", "left") - ->where('orden_trabajo_tareas.maquina_id', $maquina_id) + ->where('orden_trabajo_tareas.maquina_id', $maquina_id) // ->where('pedidos.fecha_impresion IS NOT NULL', null, false) ->where("orden_trabajo_tareas.deleted_at", null) ->where("tarea_progress.estado", 'P') diff --git a/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTareas.php b/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTareas.php index 5645741a..6667d9da 100644 --- a/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTareas.php +++ b/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTareas.php @@ -18,6 +18,8 @@ use CodeIgniter\I18n\Time;
+ +
diff --git a/ci4/app/Views/themes/vuexy/form/produccion/ot/otProgress.php b/ci4/app/Views/themes/vuexy/form/produccion/ot/otProgress.php index 87812602..2045ebdc 100755 --- a/ci4/app/Views/themes/vuexy/form/produccion/ot/otProgress.php +++ b/ci4/app/Views/themes/vuexy/form/produccion/ot/otProgress.php @@ -268,7 +268,7 @@
-
"> +
">
> @@ -320,10 +320,12 @@
-

: (HH:MM)

+ (HH:MM) +
-

:

+ (HH:MM) +
diff --git a/ci4/app/Views/themes/vuexy/form/produccion/viewOrdenTrabajoList.php b/ci4/app/Views/themes/vuexy/form/produccion/viewOrdenTrabajoList.php index 620c8805..d401c3d5 100755 --- a/ci4/app/Views/themes/vuexy/form/produccion/viewOrdenTrabajoList.php +++ b/ci4/app/Views/themes/vuexy/form/produccion/viewOrdenTrabajoList.php @@ -11,17 +11,30 @@
From 8cbe5a7051693ea4e6902f6d5ea23ac48adef27e Mon Sep 17 00:00:00 2001 From: amazuecos Date: Mon, 5 May 2025 08:04:46 +0200 Subject: [PATCH 011/127] fix papel ot color --- ci4/app/Services/ProductionService.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ci4/app/Services/ProductionService.php b/ci4/app/Services/ProductionService.php index 56d3c1d8..6091fab0 100755 --- a/ci4/app/Services/ProductionService.php +++ b/ci4/app/Services/ProductionService.php @@ -1642,22 +1642,22 @@ class ProductionService extends BaseService $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['default']; $papel_code = $papel->code_ot; if ($papel_code) { - if (strpos($papel_code, "BCLOF")) { + if (str_contains($papel_code, "BCLOF")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['blanco']; } - if (strpos($papel_code, "AH") && $papel->code == "OFF2") { + if (str_contains($papel_code, "AH")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['ahuesado']; } - if (strpos($papel_code, "MARF")) { + if (str_contains($papel_code, "MARF")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['marfil']; } - if (strpos($papel_code, "VOLAH")) { + if (str_contains($papel_code, "VOLAH")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['volumen_ahuesado']; } - if ($papel_code == "EM") { + if (str_contains($papel_code, "EM")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['estucado_mate']; } - if ($papel_code == "CGE") { + if (str_contains($papel->nombre, "CARTULINA")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['cartulina']; } } @@ -1675,22 +1675,22 @@ class ProductionService extends BaseService $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['default']; $papel_code = $papel->code_ot; if ($papel_code) { - if (strpos($papel_code, "BCLOF")) { + if (str_contains($papel_code, "BCLOF")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['blanco']; } - if (strpos($papel_code, "AH") && $papel->code == "OFF2") { + if (str_contains($papel_code, "AH")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['ahuesado']; } - if (strpos($papel_code, "MARF")) { + if (str_contains($papel_code, "MARF")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['marfil']; } - if (strpos($papel_code, "VOLAH")) { + if (str_contains($papel_code, "VOLAH")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['volumen_ahuesado']; } - if ($papel_code == "EM") { + if (str_contains($papel_code, "EM")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['estucado_mate']; } - if ($papel_code == "CGE") { + if (str_contains($papel->nombre, "CARTULINA")) { $color = $this->ordenTrabajoConfig->OT_PAPEL_COLOR['cartulina']; } } From b4dfdfa101bfe0241e813ef47c11bc8a50c4453d Mon Sep 17 00:00:00 2001 From: amazuecos Date: Mon, 5 May 2025 08:07:17 +0200 Subject: [PATCH 012/127] add ot_id in ots datatables --- ci4/app/Views/themes/vuexy/components/tables/ot_table.php | 1 + httpdocs/assets/js/safekat/components/datatables/otDatatable.js | 1 + 2 files changed, 2 insertions(+) diff --git a/ci4/app/Views/themes/vuexy/components/tables/ot_table.php b/ci4/app/Views/themes/vuexy/components/tables/ot_table.php index 21388a84..cc43a4f9 100755 --- a/ci4/app/Views/themes/vuexy/components/tables/ot_table.php +++ b/ci4/app/Views/themes/vuexy/components/tables/ot_table.php @@ -3,6 +3,7 @@ + diff --git a/httpdocs/assets/js/safekat/components/datatables/otDatatable.js b/httpdocs/assets/js/safekat/components/datatables/otDatatable.js index f6e29e1a..bd736040 100644 --- a/httpdocs/assets/js/safekat/components/datatables/otDatatable.js +++ b/httpdocs/assets/js/safekat/components/datatables/otDatatable.js @@ -15,6 +15,7 @@ class OrdenTrabajoDatatable { this.datatableColumns = [ + { data: 'id', searchable: false, sortable: false }, { data: 'pedido_id', searchable: false, sortable: false }, { data: 'fecha_encuadernado_at', searchable: false, sortable: false }, { data: 'cliente_nombre', searchable: false, sortable: false }, From 1c581db4cfbd7d92dc46bf952384577ce3ff06a0 Mon Sep 17 00:00:00 2001 From: amazuecos Date: Mon, 5 May 2025 08:27:01 +0200 Subject: [PATCH 013/127] add etiqueta envio maquina model and show in tarea card --- .../Controllers/Configuracion/Maquinas.php | 3 +++ ...0_AddEtiquetaEnvioCheckLgMaquinasTable.php | 25 +++++++++++++++++++ ci4/app/Entities/Configuracion/Maquina.php | 2 ++ ci4/app/Language/es/Maquinas.php | 1 + ci4/app/Models/Configuracion/MaquinaModel.php | 3 ++- .../maquinas/_maquinaFormItems.php | 14 ++++++++++- .../maquinista/viewMaquinistaMaquinaTarea.php | 10 +++++--- 7 files changed, 52 insertions(+), 6 deletions(-) create mode 100755 ci4/app/Database/Migrations/2025-05-05-080900_AddEtiquetaEnvioCheckLgMaquinasTable.php diff --git a/ci4/app/Controllers/Configuracion/Maquinas.php b/ci4/app/Controllers/Configuracion/Maquinas.php index 384f0026..3ee7c046 100755 --- a/ci4/app/Controllers/Configuracion/Maquinas.php +++ b/ci4/app/Controllers/Configuracion/Maquinas.php @@ -207,6 +207,9 @@ class Maquinas extends \App\Controllers\BaseResourceController if ($this->request->getPost('is_inkjet') == null) { $sanitizedData['is_inkjet'] = false; } + if ($this->request->getPost('etiqueta_envio') == null) { + $sanitizedData['etiqueta_envio'] = false; + } // JJO $sanitizedData['user_updated_id'] = auth()->user()->id; diff --git a/ci4/app/Database/Migrations/2025-05-05-080900_AddEtiquetaEnvioCheckLgMaquinasTable.php b/ci4/app/Database/Migrations/2025-05-05-080900_AddEtiquetaEnvioCheckLgMaquinasTable.php new file mode 100755 index 00000000..1f25bcc7 --- /dev/null +++ b/ci4/app/Database/Migrations/2025-05-05-080900_AddEtiquetaEnvioCheckLgMaquinasTable.php @@ -0,0 +1,25 @@ + [ + 'type' => 'BOOL', + 'default' => false + ], + ]; + public function up() + { + + $this->forge->addColumn('lg_maquinas',$this->COLUMNS); + } + + public function down() + { + $this->forge->dropColumn('lg_maquinas',array_keys($this->COLUMNS)); + } +} diff --git a/ci4/app/Entities/Configuracion/Maquina.php b/ci4/app/Entities/Configuracion/Maquina.php index 1ccdef6a..6b9f6cf8 100755 --- a/ci4/app/Entities/Configuracion/Maquina.php +++ b/ci4/app/Entities/Configuracion/Maquina.php @@ -42,6 +42,7 @@ class Maquina extends \CodeIgniter\Entity\Entity "updated_at" => null, "user_created_id" => 0, "user_updated_id" => 0, + "etiqueta_envio" => false ]; protected $casts = [ "is_padre" => "boolean", @@ -57,6 +58,7 @@ class Maquina extends \CodeIgniter\Entity\Entity "duracion_jornada" => "int", "orden_planning" => "int", "is_rotativa" => "boolean", + "etiqueta_envio" => "boolean", "precio_tinta_negro" => "float", "is_inkjet" => "boolean", "precio_tinta_color" => "float", diff --git a/ci4/app/Language/es/Maquinas.php b/ci4/app/Language/es/Maquinas.php index 6971e9fa..efb9ce08 100755 --- a/ci4/app/Language/es/Maquinas.php +++ b/ci4/app/Language/es/Maquinas.php @@ -20,6 +20,7 @@ return [ 'isPadre' => 'Usar para variante?', 'isRotativa' => 'Es Rotativa?', 'isTinta' => 'Inkjet', + 'isEtiquetaEnvio' => 'Etiqueta envío', 'manipulado' => 'manipulado', 'maquina' => 'Maquina', 'maquinaList' => 'Lista Máquinas', diff --git a/ci4/app/Models/Configuracion/MaquinaModel.php b/ci4/app/Models/Configuracion/MaquinaModel.php index cbe249f8..74e96cb7 100755 --- a/ci4/app/Models/Configuracion/MaquinaModel.php +++ b/ci4/app/Models/Configuracion/MaquinaModel.php @@ -52,7 +52,8 @@ class MaquinaModel extends \App\Models\BaseModel "deleted_at", "is_deleted", "user_created_id", - "user_updated_id" + "user_updated_id", + "etiqueta_envio", ]; protected $returnType = "App\Entities\Configuracion\Maquina"; diff --git a/ci4/app/Views/themes/vuexy/form/configuracion/maquinas/_maquinaFormItems.php b/ci4/app/Views/themes/vuexy/form/configuracion/maquinas/_maquinaFormItems.php index 1b2408b9..2b64ba70 100755 --- a/ci4/app/Views/themes/vuexy/form/configuracion/maquinas/_maquinaFormItems.php +++ b/ci4/app/Views/themes/vuexy/form/configuracion/maquinas/_maquinaFormItems.php @@ -173,7 +173,19 @@ - +
+
+ etiqueta_envio == true ? 'checked' : ''; ?> + > + +
+
- - - - - - - - - - - - - - +
+
+ + + + + + + + + + + + + + + + +
+
- -
diff --git a/httpdocs/assets/js/safekat/pages/configuracion/imposiciones/imposicion.js b/httpdocs/assets/js/safekat/pages/configuracion/imposiciones/imposicion.js index 5d51fd5f..68f5b44a 100644 --- a/httpdocs/assets/js/safekat/pages/configuracion/imposiciones/imposicion.js +++ b/httpdocs/assets/js/safekat/pages/configuracion/imposiciones/imposicion.js @@ -29,7 +29,8 @@ class Imposicion { this.imposicionForm = new ImposicionForm(this.itemForm) this.imposicionForm.init() } - new() { + initNew() { + this.imposicionForm = new ImposicionForm(this.itemForm) this.imposicionForm.initNew() } init_imposicion_esquema_form() { diff --git a/httpdocs/assets/js/safekat/pages/configuracion/imposiciones/new.js b/httpdocs/assets/js/safekat/pages/configuracion/imposiciones/new.js index 449b7081..277d7175 100644 --- a/httpdocs/assets/js/safekat/pages/configuracion/imposiciones/new.js +++ b/httpdocs/assets/js/safekat/pages/configuracion/imposiciones/new.js @@ -4,5 +4,5 @@ import Imposicion from "./imposicion.js" $(() => { console.log("Imposicion") let imposicion = new Imposicion() - imposicion.new() + imposicion.initNew() }) \ No newline at end of file From d2c6d131b31248c187c8026211f7ccaa1d29c206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 5 May 2025 16:23:12 +0200 Subject: [PATCH 022/127] cambiado el campo cajas --- ci4/app/Services/ImpresoraEtiquetaService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci4/app/Services/ImpresoraEtiquetaService.php b/ci4/app/Services/ImpresoraEtiquetaService.php index 46f4cd9f..d2e5026d 100755 --- a/ci4/app/Services/ImpresoraEtiquetaService.php +++ b/ci4/app/Services/ImpresoraEtiquetaService.php @@ -170,7 +170,7 @@ class ImpresoraEtiquetaService extends BaseService "titulo" => $datos->titulo, "cantidad" => $cantidad + $ejemplares_caja <= $datos->unidades ? $ejemplares_caja : $datos->unidades-$cantidad, "tirada" => $datos->unidades, - "cajas" => $cajas, + "cajas" => $i . '/' . $cajas, "ean" => str_replace("-", "", $datos->isbn), "nombre" => null, "direccion" => null, From 1ebc22c74b292cc5d8205c8439c0e41019932890 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Mon, 5 May 2025 16:30:11 +0200 Subject: [PATCH 023/127] Modificaciones --- ci4/app/Helpers/menu_helper.php | 32 +++++++++++++++++++ .../Views/themes/vuexy/main/defaultlayout.php | 10 +++--- 2 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 ci4/app/Helpers/menu_helper.php diff --git a/ci4/app/Helpers/menu_helper.php b/ci4/app/Helpers/menu_helper.php new file mode 100644 index 00000000..3eaf44ca --- /dev/null +++ b/ci4/app/Helpers/menu_helper.php @@ -0,0 +1,32 @@ + Date: Mon, 5 May 2025 16:31:55 +0200 Subject: [PATCH 024/127] quitado el boton en las nuevas --- .../Configuracion/Imposiciones.php | 2 ++ .../imposiciones/_imposicionFormItems.php | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ci4/app/Controllers/Configuracion/Imposiciones.php b/ci4/app/Controllers/Configuracion/Imposiciones.php index e47ad6be..b798a2c2 100755 --- a/ci4/app/Controllers/Configuracion/Imposiciones.php +++ b/ci4/app/Controllers/Configuracion/Imposiciones.php @@ -67,6 +67,7 @@ class Imposiciones extends BaseController ['title' => lang("App.menu_imposiciones"), 'route' => route_to("imposicionList"), 'active' => true], ]; + $this->viewData["method"] = "add"; return view(static::$viewPath . 'viewImposicionNewForm', $this->viewData); } public function add_esquema() @@ -88,6 +89,7 @@ class Imposiciones extends BaseController ]; } + $this->viewData["method"] = "edit"; return view(static::$viewPath . 'viewImposicionForm', $this->viewData); } public function edit_imposicion_esquema($imposicion_esquema_id = null) diff --git a/ci4/app/Views/themes/vuexy/form/configuracion/imposiciones/_imposicionFormItems.php b/ci4/app/Views/themes/vuexy/form/configuracion/imposiciones/_imposicionFormItems.php index 65ed833d..200c56fa 100755 --- a/ci4/app/Views/themes/vuexy/form/configuracion/imposiciones/_imposicionFormItems.php +++ b/ci4/app/Views/themes/vuexy/form/configuracion/imposiciones/_imposicionFormItems.php @@ -48,16 +48,19 @@ -
-
+ + +
+ -
- -
-
+ + +
+
+ +
+
+ \ No newline at end of file From 302d12da1e8b5373ebe0e40ab08aa3450b9b050a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 5 May 2025 17:34:51 +0200 Subject: [PATCH 025/127] =?UTF-8?q?ahora=20el=20pod=20puede=20ser=20negro?= =?UTF-8?q?=20estandar.=20Para=20presupuestos=20no=20importados,=20si=20no?= =?UTF-8?q?=5Fenvio=5Fbase=20no=20se=20a=C3=B1ade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci4/app/Controllers/Presupuestos/Presupuestoadmin.php | 6 ++++++ ci4/app/Controllers/Presupuestos/Presupuestocliente.php | 8 ++++---- .../form/presupuestos/admin/viewPresupuestoadminForm.php | 2 ++ .../js/safekat/pages/presupuestoAdmin/sections/envios.js | 3 +++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ci4/app/Controllers/Presupuestos/Presupuestoadmin.php b/ci4/app/Controllers/Presupuestos/Presupuestoadmin.php index 28e87c50..a2a5b194 100755 --- a/ci4/app/Controllers/Presupuestos/Presupuestoadmin.php +++ b/ci4/app/Controllers/Presupuestos/Presupuestoadmin.php @@ -202,6 +202,8 @@ class Presupuestoadmin extends \App\Controllers\BaseResourceController $this->viewData['pais_default_id'] = model('App\Models\Configuracion\ConfigVariableModel')->getVariable('id_pais_defecto')->value; $this->viewData['pais_default'] = model('App\Models\Configuracion\PaisModel')->find($this->viewData['pais_default_id'])->nombre; + $this->viewData['no_envio_base'] = 0; + $this->viewData['formAction'] = route_to('createPresupuestoAdmin', $tipo_impresion_id); $this->viewData = array_merge($this->viewData, $this->getStringsFromTipoImpresion($tipo_impresion_id)); @@ -434,6 +436,10 @@ class Presupuestoadmin extends \App\Controllers\BaseResourceController $this->viewData['POD'] = $this->getPOD(); + $this->viewData['no_envio_base'] = model('App\Models\Clientes\ClienteModel')->where('id', $presupuestoEntity->cliente_id)->first(); + if($this->viewData['no_envio_base']) + $this->viewData['no_envio_base'] = $this->viewData['no_envio_base']->no_envio_base; + $this->viewData['serviciosAutomaticos'] = [ 'solapas_cubierta' => model('App\Models\Configuracion\ConfigVariableModel')->getVariable('servicio_solapas_cubierta')->value, 'solapas_sobrecubierta' => model('App\Models\Configuracion\ConfigVariableModel')->getVariable('servicio_solapas_sobrecubierta')->value, diff --git a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php index d528e809..c40ecc4c 100755 --- a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php +++ b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php @@ -333,7 +333,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController $cliente_model = model(('App\Models\Clientes\ClienteModel')); $cliente = $cliente_model->find($cliente_id); // Para POD siempre es HQ - if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) { + if ($tirada[0] <= $POD && $isColor && !$cliente->forzar_rotativa_pod) { $isHq = true; } $forzarRotativa = false; @@ -760,8 +760,8 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController $cliente_model = model(('App\Models\Clientes\ClienteModel')); $cliente = $cliente_model->find($cliente_id); - // Para POD siempre es HQ - if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) { + // Para POD siempre es HQ cuando es color + if ($tirada[0] <= $POD && $isColor && !$cliente->forzar_rotativa_pod) { $isHq = true; } $forzarRotativa = false; @@ -2081,7 +2081,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController $cliente_model = model(('App\Models\Clientes\ClienteModel')); $cliente = $cliente_model->find($cliente_id); // Para POD siempre es HQ - if ($tirada[$t] <= $POD && !$cliente->forzar_rotativa_pod) { + if ($tirada[$t] <= $POD && $isColor && !$cliente->forzar_rotativa_pod) { $isHq = true; } $forzarRotativa = false; diff --git a/ci4/app/Views/themes/vuexy/form/presupuestos/admin/viewPresupuestoadminForm.php b/ci4/app/Views/themes/vuexy/form/presupuestos/admin/viewPresupuestoadminForm.php index 6ef1a1c5..2e47dec5 100755 --- a/ci4/app/Views/themes/vuexy/form/presupuestos/admin/viewPresupuestoadminForm.php +++ b/ci4/app/Views/themes/vuexy/form/presupuestos/admin/viewPresupuestoadminForm.php @@ -24,6 +24,8 @@ + diff --git a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/envios.js b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/envios.js index cfb79356..86c22c82 100644 --- a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/envios.js +++ b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/envios.js @@ -327,6 +327,9 @@ class Envios { async updateTiradaBase() { + if($('#noEnvioBase').val() == 1) + return; + const self = this; var peso_total_libro = this.get_peso_libro(); From 899365f2c29b7caf57aa9effbb4d9248a1ad8e80 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Mon, 5 May 2025 17:35:22 +0200 Subject: [PATCH 026/127] Puesto en grupo beta opcion Catalogo -> Importar --- .../Views/themes/vuexy/main/menus/catalogo_menu.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ci4/app/Views/themes/vuexy/main/menus/catalogo_menu.php b/ci4/app/Views/themes/vuexy/main/menus/catalogo_menu.php index 1f00317d..b03aece0 100755 --- a/ci4/app/Views/themes/vuexy/main/menus/catalogo_menu.php +++ b/ci4/app/Views/themes/vuexy/main/menus/catalogo_menu.php @@ -25,11 +25,13 @@ if (auth()->user()->can('catalogo.menu')) { - + user()->inGroup('beta')) { ?> + + \ No newline at end of file From 4120ded07bd966c11cf13c2614913288d0668a2f Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Mon, 5 May 2025 17:37:07 +0200 Subject: [PATCH 027/127] Renombrado importador desde catalogo a RA-MA --- ci4/app/Language/es/App.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci4/app/Language/es/App.php b/ci4/app/Language/es/App.php index 085766ef..66873e89 100755 --- a/ci4/app/Language/es/App.php +++ b/ci4/app/Language/es/App.php @@ -721,7 +721,7 @@ return [ "menu_digitalizacion" => "Digitalización", "menu_importadores" => "Importadores", - "menu_importadores_catalogo" => "Desde catálogo", + "menu_importadores_catalogo" => "RA-MA", //"Desde catálogo", "menu_importadores_bubok" => "Bubok", "menu_catalogo" => "Catálogo", From 75f06c44a1705d1813d34907301c6790eed9f153 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Mon, 5 May 2025 18:38:30 +0200 Subject: [PATCH 028/127] =?UTF-8?q?A=C3=B1adida=20opcion=20'uso'=20en=20la?= =?UTF-8?q?s=20queries=20de=20catalogo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Importadores/ImportadorCatalogo.php | 4 ++-- .../js/safekat/pages/catalogo/catalogo.js | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php index e2ebb080..678aebf0 100644 --- a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php +++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php @@ -248,11 +248,11 @@ class ImportadorCatalogo extends BaseResourceController 'entrega_taller' => 1, ]; - /*return $this->response->setJSON([ + return $this->response->setJSON([ 'success' => true, 'message' => 'Libro encontrado y preparado para importar.', 'data' => $dataToImport - ]);*/ + ]); // Procedemos a intentar guardar el presupuesto diff --git a/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js b/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js index 5a460f8e..9a9f1a58 100644 --- a/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js +++ b/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js @@ -31,6 +31,7 @@ class Catalogo { tirada: () => this.tirada_no_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'interior', sopalas: 0, lomo: 0, tipo: () => this.tipo_impresion.val().includes('hq') ? 'negrohq' : 'negro', @@ -42,6 +43,7 @@ class Catalogo { tirada: () => this.tirada_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'interior', sopalas: 0, lomo: 0, tipo: () => this.tipo_impresion.val().includes('hq') ? 'negrohq' : 'negro', @@ -54,6 +56,7 @@ class Catalogo { tirada: () => this.tirada_no_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'interior', sopalas: 0, lomo: 0, tipo: () => this.tipo_impresion.val().includes('hq') ? 'negrohq' : 'negro', @@ -66,6 +69,7 @@ class Catalogo { tirada: () => this.tirada_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'interior', sopalas: 0, lomo: 0, tipo: () => this.tipo_impresion.val().includes('hq') ? 'negrohq' : 'negro', @@ -79,6 +83,7 @@ class Catalogo { tirada: () => this.tirada_no_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'interior', sopalas: 0, lomo: 0, tipo: () => this.tipo_impresion.val().includes('hq') ? 'colorhq' : 'color', @@ -90,6 +95,7 @@ class Catalogo { tirada: () => this.tirada_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'interior', sopalas: 0, lomo: 0, tipo: () => this.tipo_impresion.val().includes('hq') ? 'colorhq' : 'color', @@ -102,6 +108,7 @@ class Catalogo { tirada: () => this.tirada_no_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'interior', sopalas: 0, lomo: 0, tipo: () => this.tipo_impresion.val().includes('hq') ? 'colorhq' : 'color', @@ -114,6 +121,7 @@ class Catalogo { tirada: () => this.tirada_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'interior', sopalas: 0, lomo: 0, tipo: () => this.tipo_impresion.val().includes('hq') ? 'colorhq' : 'color', @@ -126,6 +134,7 @@ class Catalogo { tirada: () => this.tirada_no_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'cubierta', sopalas: () => $('#cubierta_ancho_solapas').val(), lomo: () => 0, tipo: 'colorhq', @@ -138,6 +147,7 @@ class Catalogo { tirada: () => this.tirada_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'cubierta', sopalas: () => $('#cubierta_ancho_solapas').val(), lomo: () => 0, tipo: 'colorhq', @@ -151,6 +161,7 @@ class Catalogo { tirada: () => this.tirada_no_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'cubierta', sopalas: () => $('#cubierta_ancho_solapas').val(), lomo: 0, tipo: 'colorhq', @@ -163,6 +174,7 @@ class Catalogo { tirada: () => this.tirada_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'cubierta', sopalas: () => $('#cubierta_ancho_solapas').val(), lomo: 0, tipo: 'colorhq', @@ -184,10 +196,10 @@ class Catalogo { tirada: () => this.tirada_no_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'sobrecubierta', sopalas: () => $('#sobrecubierta_ancho_solapas').val(), lomo: () => 0, tipo: 'colorhq', - uso: 'sobrecubierta', }); this.selectPapelSobrecubiertaPod = new ClassSelect($("#sobrecubierta_pod_papel_id"), '/presupuestoadmin/papelgenerico', "Seleccione un papel", false, @@ -196,10 +208,10 @@ class Catalogo { tirada: () => this.tirada_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'sobrecubierta', sopalas: () => $('#sobrecubierta_ancho_solapas').val(), lomo: () => 0, tipo: 'colorhq', - uso: 'sobrecubierta', }); this.selectGramajeSobrecubierta = new ClassSelect($('#sobrecubierta_gramaje'), '/presupuestoadmin/papelgramaje', 'Seleccione un gramaje', false, @@ -209,6 +221,7 @@ class Catalogo { tirada: () => this.tirada_no_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'sobrecubierta', sopalas: () => $('#sobrecubierta_ancho_solapas').val(), lomo: 0, tipo: 'colorhq', @@ -221,6 +234,7 @@ class Catalogo { tirada: () => this.tirada_pod, ancho: () => this.getDimensionLibro().ancho, alto: () => this.getDimensionLibro().alto, + uso: 'sobrecubierta', sopalas: () => $('#sobrecubierta_ancho_solapas').val(), lomo: 0, tipo: 'colorhq', From 514905ff4755548acf21900454b1f953e88a48b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 5 May 2025 18:52:16 +0200 Subject: [PATCH 029/127] terminado --- .../Logistica/EtiquetasTitulosController.php | 2 +- .../Logistica/LogisticaController.php | 2 +- .../Presupuestos/Presupuestocliente.php | 2 +- ci4/app/Services/PresupuestoService.php | 2 +- .../presupuestoAdmin/sections/servicios.js | 40 +++++++++---------- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php b/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php index 2026d8b8..d82805a0 100644 --- a/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php +++ b/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php @@ -166,7 +166,7 @@ class EtiquetasTitulosController extends BaseController $impresoras = $modelImpresora->select('id, name') ->where('deleted_at', null) ->where('tipo', 1) - ->orderBy('name', 'asc') + ->orderBy('name', 'desc') ->findAll(); $etiquetaEntity->impresoras = $impresoras; diff --git a/ci4/app/Controllers/Logistica/LogisticaController.php b/ci4/app/Controllers/Logistica/LogisticaController.php index 586bb83d..b69b0f4c 100755 --- a/ci4/app/Controllers/Logistica/LogisticaController.php +++ b/ci4/app/Controllers/Logistica/LogisticaController.php @@ -345,7 +345,7 @@ class LogisticaController extends BaseController $impresoras = $modelImpresora->select('id, name') ->where('deleted_at', null) ->where('tipo', 1) - ->orderBy('name', 'asc') + ->orderBy('name', 'desc') ->findAll(); $envioEntity->impresoras = $impresoras; diff --git a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php index c40ecc4c..9abe57a5 100755 --- a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php +++ b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php @@ -2272,7 +2272,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController return $return_data; } - $cantidad_total = intval($datosPedido->tirada) + intval($datosPedido->merma); + $cantidad_total = intval($datosPedido->tirada);// + intval($datosPedido->merma); // Acabado Cubierta if (intval($datos_entrada['cubierta']['acabado']) != 0) { diff --git a/ci4/app/Services/PresupuestoService.php b/ci4/app/Services/PresupuestoService.php index 56d7dfdc..c8aa7d05 100755 --- a/ci4/app/Services/PresupuestoService.php +++ b/ci4/app/Services/PresupuestoService.php @@ -1895,7 +1895,7 @@ class PresupuestoService extends BaseService "user_updated_id" => auth()->user()->id, ]; $id_linea = $model_pedido_linea->insert($data_pedido_linea); - PedidoXMLService::generate_xml($pedido_id); + //PedidoXMLService::generate_xml($pedido_id); } if ($id_linea != 0 && $pedido_id != 0) { diff --git a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/servicios.js b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/servicios.js index 2fc81df3..e58b2d91 100644 --- a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/servicios.js +++ b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/servicios.js @@ -461,10 +461,10 @@ class ServiciosAcabado { if (parseInt($('#tirada').val()) > 0) { var tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } else { var tirada = 0 @@ -536,10 +536,10 @@ class ServiciosAcabado { let tirada = 0; if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } if (tarifa_ids.length > 0 && tirada > 0) { const data = { @@ -586,10 +586,10 @@ class ServiciosAcabado { let tirada = 0 if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } let datos = { tirada: tirada, @@ -1072,10 +1072,10 @@ class ServiciosEncuadernacion { let tirada = 0; if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()); - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } let paginas = 0; @@ -1176,10 +1176,10 @@ class ServiciosEncuadernacion { let tirada = 0; if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } let paginas = 0; if (parseInt($('#paginas').val()) > 0) { @@ -1221,10 +1221,10 @@ class ServiciosEncuadernacion { let tirada = 0; if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } let paginas = 0; if (parseInt($('#paginas').val()) > 0) { @@ -1267,10 +1267,10 @@ class ServiciosEncuadernacion { let tirada = 0; if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } let paginas = 0; if (parseInt($('#paginas').val()) > 0) { @@ -1559,10 +1559,10 @@ class ServiciosManipulado { let tirada = 0; if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } let datos = { @@ -1600,10 +1600,10 @@ class ServiciosManipulado { let tirada = 0; if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } if (tarifa_ids.length > 0) { @@ -1633,10 +1633,10 @@ class ServiciosManipulado { let tirada = 0; if (parseInt($('#tirada').val()) > 0) { tirada = parseInt($('#tirada').val()) - var merma = parseInt($('#merma').val()) + /*var merma = parseInt($('#merma').val()) if (merma && merma > 0) { tirada = tirada + merma; - } + }*/ } let datos = { From bf146d4024bf32706c63a1b50892ad8b962edb5f Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Mon, 5 May 2025 18:53:44 +0200 Subject: [PATCH 030/127] Revision de la entidad de catalogo libros --- .../Entities/Catalogo/CatalogoLibroEntity.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/ci4/app/Entities/Catalogo/CatalogoLibroEntity.php b/ci4/app/Entities/Catalogo/CatalogoLibroEntity.php index e50d1a5f..780d544d 100644 --- a/ci4/app/Entities/Catalogo/CatalogoLibroEntity.php +++ b/ci4/app/Entities/Catalogo/CatalogoLibroEntity.php @@ -10,6 +10,7 @@ use App\Models\Tarifas\Acabados\ServicioAcabadoModel; use App\Models\Clientes\ClienteModel; class CatalogoLibroEntity extends Entity { + protected $attributes = [ 'id' => null, 'cliente_id' => null, @@ -44,8 +45,6 @@ class CatalogoLibroEntity extends Entity 'sello' => null, 'paginas' => 0, 'tipo_impresion' => null, - 'solapas_ancho' => 0.00, - 'cubiertas_ancho' => 0.00, 'comentarios' => '', 'negro_paginas' => null, 'negro_papel' => null, @@ -63,6 +62,8 @@ class CatalogoLibroEntity extends Entity 'cubierta_papel' => null, 'cubierta_papel_id' => null, 'cubierta_gramaje' => null, + 'cubierta_ancho_solapas' => 0.00, + 'cubierta_acabado_id' => null, 'cubierta_acabado' => null, 'cubierta_pod_papel_id' => null, 'cubierta_pod_gramaje' => null, @@ -70,10 +71,12 @@ class CatalogoLibroEntity extends Entity 'sobrecubierta_papel' => null, 'sobrecubierta_papel_id' => null, 'sobrecubierta_gramaje' => null, + 'sobrecubierta_acabado_id' => null, 'sobrecubierta_acabado' => null, 'sobrecubierta_pod_papel_id' => null, + 'sobrecubierta_ancho_solapas' => 0.00, 'sobrecubierta_pod_gramaje' => null, - 'encuardenacion_id' => 'null', + 'encuadernacion_id' => null, 'ubicacion' => null, 'created_at' => null, 'updated_at' => null, @@ -97,8 +100,6 @@ class CatalogoLibroEntity extends Entity 'num_ilustr_color' => '?int', 'num_ilustr_bn' => '?int', 'paginas' => 'int', - 'solapas_ancho' => 'float', - 'cubiertas_ancho' => 'float', 'negro_paginas' => '?int', 'negro_gramaje' => '?float', 'negro_papel_id' => '?int', @@ -113,15 +114,19 @@ class CatalogoLibroEntity extends Entity 'cubierta_gramaje' => '?float', 'cubierta_papel_id' => '?int', 'cubierta_pod_papel_id' => '?int', + 'cubierta_ancho_solapas' => 'float', 'cubierta_pod_gramaje' => '?float', + 'cubierta_acabado_id' => '?int', 'sobrecubierta_paginas' => '?int', 'sobrecubierta_gramaje' => '?float', 'sobrecubierta_papel_id' => '?int', 'sobrecubierta_pod_papel_id' => '?int', + 'sobrecubierta_ancho_solapas' => 'float', 'sobrecubierta_pod_gramaje' => '?float', + 'sobrecubierta_acabado_id' => '?int', + 'encuadernacion_id' => '?int', 'fecha_disponibilidad' => 'datetime', 'fecha_public' => 'datetime', - ]; public function getClienteName() From 21e907ad5034e5fd57b08165bab145c3b689cc50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 5 May 2025 19:27:17 +0200 Subject: [PATCH 031/127] prueba --- ci4/app/Services/EtiquetasTitulosService.php | 3 +-- ci4/app/Services/ImpresoraEtiquetaService.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ci4/app/Services/EtiquetasTitulosService.php b/ci4/app/Services/EtiquetasTitulosService.php index 55c6b53e..af9c579a 100644 --- a/ci4/app/Services/EtiquetasTitulosService.php +++ b/ci4/app/Services/EtiquetasTitulosService.php @@ -283,7 +283,6 @@ class EtiquetasTitulosService array_push($data['grupos'], [ ]); - $prefix = 1; $lineas = array_filter($etiquetas_lineas, function ($linea) use ($caja) { return $linea->numero_caja == $caja; }); @@ -313,7 +312,7 @@ class EtiquetasTitulosService $data['grupos'][$index_etiqueta][] = [ - 'prefix' => $caja, + 'prefix' => $lineaCounter, 'titulo' => mb_substr($datos_etiqueta->titulo, 0, 40), 'cantidad' => $linea->unidades, 'tirada' => $datos_etiqueta->total_tirada, diff --git a/ci4/app/Services/ImpresoraEtiquetaService.php b/ci4/app/Services/ImpresoraEtiquetaService.php index d2e5026d..88e4e4f2 100755 --- a/ci4/app/Services/ImpresoraEtiquetaService.php +++ b/ci4/app/Services/ImpresoraEtiquetaService.php @@ -96,7 +96,7 @@ class ImpresoraEtiquetaService extends BaseService // Crear variables específicas del grupo foreach ($grupo as $libro) { - $prefix = $libro['prefix']; + $prefix = $libro['prefix']==0 ? '' : $libro['prefix']; $variables = [ "titulo$prefix" => $libro['titulo'], From 247fa7e6f934732ecc3ef922d337054fdbe0aa61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 5 May 2025 19:36:33 +0200 Subject: [PATCH 032/127] prueba2 --- ci4/app/Services/EtiquetasTitulosService.php | 4 ++-- ci4/app/Services/ImpresoraEtiquetaService.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci4/app/Services/EtiquetasTitulosService.php b/ci4/app/Services/EtiquetasTitulosService.php index af9c579a..35d617a8 100644 --- a/ci4/app/Services/EtiquetasTitulosService.php +++ b/ci4/app/Services/EtiquetasTitulosService.php @@ -312,12 +312,12 @@ class EtiquetasTitulosService $data['grupos'][$index_etiqueta][] = [ - 'prefix' => $lineaCounter, + 'prefix' => $lineaCounter+1, 'titulo' => mb_substr($datos_etiqueta->titulo, 0, 40), 'cantidad' => $linea->unidades, 'tirada' => $datos_etiqueta->total_tirada, 'ean' => str_replace('-', '', $datos_etiqueta->isbn), - 'npedido' => $datos_etiqueta->id, + 'npedido' => $datos_etiqueta->id_pedido, 'refcliente' => $datos_etiqueta->referencia_cliente, ]; diff --git a/ci4/app/Services/ImpresoraEtiquetaService.php b/ci4/app/Services/ImpresoraEtiquetaService.php index 88e4e4f2..fa823e24 100755 --- a/ci4/app/Services/ImpresoraEtiquetaService.php +++ b/ci4/app/Services/ImpresoraEtiquetaService.php @@ -96,7 +96,7 @@ class ImpresoraEtiquetaService extends BaseService // Crear variables específicas del grupo foreach ($grupo as $libro) { - $prefix = $libro['prefix']==0 ? '' : $libro['prefix']; + $prefix = $libro['prefix']==1 ? '' : $libro['prefix']; $variables = [ "titulo$prefix" => $libro['titulo'], From c6fb4b32131bbf582c223d98a907d7e32a0d9265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 5 May 2025 19:42:45 +0200 Subject: [PATCH 033/127] terminado --- .../assets/js/safekat/pages/logistica/etiquetaEdit.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/httpdocs/assets/js/safekat/pages/logistica/etiquetaEdit.js b/httpdocs/assets/js/safekat/pages/logistica/etiquetaEdit.js index 0ac7b9ca..3139bebb 100644 --- a/httpdocs/assets/js/safekat/pages/logistica/etiquetaEdit.js +++ b/httpdocs/assets/js/safekat/pages/logistica/etiquetaEdit.js @@ -64,6 +64,11 @@ class EtiquetaEdit { } }); + if (ids.length == 0) { + popErrorAlert('Seleccione al menos una linea'); + return; + } + $.post( '/etiquetasTitulos/imprimirEtiquetas', { @@ -283,6 +288,9 @@ class EtiquetaEdit { } _addLineas() { + + const self = this; + if (this.buscador.item.select2('data').length > 0) { let maxUnidades = 0; From 10b5ae911a1df853f3f14fd3a6f8c2ddf744c8e2 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Mon, 5 May 2025 20:13:59 +0200 Subject: [PATCH 034/127] =?UTF-8?q?A=C3=B1adidas=20mejoras=20propuestas=20?= =?UTF-8?q?por=20Manolo=20a=20la=20importacion=20de=20RAMA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Importadores/ImportadorCatalogo.php | 46 +++++++++++++------ .../importadores/catalogo/catalogo_tool.js | 28 ++++++++--- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php index 678aebf0..c77b0fea 100644 --- a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php +++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php @@ -3,6 +3,7 @@ namespace App\Controllers\Importadores; use App\Controllers\BaseResourceController; use App\Entities\Catalogo\CatalogoLibroEntity; +use App\Models\Presupuestos\PresupuestoModel; use App\Models\Catalogo\CatalogoLibroModel; use App\Controllers\Presupuestos\Presupuestocliente; use App\Services\PresupuestoService; @@ -45,7 +46,7 @@ class ImportadorCatalogo extends BaseResourceController $viewData = [ 'pageSubTitle' => lang('Basic.global.ManageAllRecords', [lang('Importador.importadorCatalogoTitle')]), - + ]; $viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class @@ -58,37 +59,51 @@ class ImportadorCatalogo extends BaseResourceController { $json = $this->request->getJSON(); - if (!$json || !isset($json->fila[0])) { + // Validación inicial del JSON y del ISBN + if (!$json || !isset($json->fila[0]) || empty(trim($json->fila[0]))) { return $this->response->setJSON([ 'apto' => false, - 'reason' => 'Datos inválidos' + 'reason' => 'ISBN no proporcionado o datos inválidos' ]); } - $input = trim($json->fila[0]); // Asumimos que 'input' es el primer campo de la fila + $input = trim($json->fila[0]); // ISBN + $refCliente = isset($json->fila[1]) ? trim($json->fila[1]) : null; - if (empty($input)) { + // Validar formato del refCliente (esperado: idpedido-idlinea) + if (empty($refCliente) || strpos($refCliente, '-') === false) { return $this->response->setJSON([ 'apto' => false, - 'reason' => 'ISBN no proporiconado' + 'reason' => 'Ref. cliente inválido' + ]); + } + + // 1. Comprobar duplicado en tabla de presupuestos + $presupuestoModel = new PresupuestoModel(); // Usa el modelo real que corresponda + $yaExiste = $presupuestoModel->where('referencia_cliente', $refCliente)->first(); + + if ($yaExiste) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'Referencia ya importada' ]); } $catalogoModel = new CatalogoLibroModel(); - // 1. Buscar por ISBN exacto + // 2. Buscar por ISBN exacto $libroPorIsbn = $catalogoModel->where('isbn', $input)->first(); - if ($libroPorIsbn) { return $this->response->setJSON([ 'apto' => true ]); } - // 2. Buscar por EAN sin guiones + // 3. Buscar por EAN sin guiones $eanLimpio = str_replace('-', '', $input); - - $libroPorEan = $catalogoModel->where('REPLACE(ean, "-", "")', $eanLimpio)->first(); + $libroPorEan = $catalogoModel + ->where('REPLACE(ean, "-", "")', $eanLimpio, false) // false para evitar escapado automático + ->first(); if ($libroPorEan) { return $this->response->setJSON([ @@ -96,7 +111,7 @@ class ImportadorCatalogo extends BaseResourceController ]); } - // No encontrado + // 4. No encontrado return $this->response->setJSON([ 'apto' => false, 'reason' => 'No encontrado en catálogo' @@ -105,6 +120,7 @@ class ImportadorCatalogo extends BaseResourceController + public function importarFila() { $json = $this->request->getJSON(); @@ -248,11 +264,11 @@ class ImportadorCatalogo extends BaseResourceController 'entrega_taller' => 1, ]; - return $this->response->setJSON([ + /*return $this->response->setJSON([ 'success' => true, 'message' => 'Libro encontrado y preparado para importar.', 'data' => $dataToImport - ]); + ]);*/ // Procedemos a intentar guardar el presupuesto @@ -287,7 +303,7 @@ class ImportadorCatalogo extends BaseResourceController $response['data']['sk_id'], $precio_compra, $tirada, - null, + null, true ); if ($respuesta_ajuste['warning'] == true) { diff --git a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js index 5b9e19c8..4423e5c5 100644 --- a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js +++ b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js @@ -57,7 +57,8 @@ document.addEventListener('DOMContentLoaded', function () { headerMap[name.toLowerCase()] = idx; }); - const missing = TABLE_COLUMNS.filter(col => !(col in headerMap)); + const requiredColumns = ["idpedido", ...TABLE_COLUMNS]; + const missing = requiredColumns.filter(col => !(col in headerMap)); if (missing.length > 0) { Swal.fire({ title: 'Error', @@ -73,7 +74,19 @@ document.addEventListener('DOMContentLoaded', function () { const rows = []; for (let i = 1; i < data.length; i++) { - const rowData = TABLE_COLUMNS.map(col => data[i][headerMap[col]] ?? ''); + // Leer columnas necesarias desde Excel + const input = data[i][headerMap["input"]] ?? ''; + const idlinea = data[i][headerMap["idlinea"]] ?? ''; + const idpedido = data[i][headerMap["idpedido"]] ?? ''; // aunque no esté en TABLE_COLUMNS, lo usamos aquí + const descripcion = data[i][headerMap["descripcion"]] ?? ''; + const cnt_pedida = data[i][headerMap["cnt_pedida"]] ?? ''; + const precio_compra = data[i][headerMap["precio_compra"]] ?? ''; + + // Componer Ref. Cliente + const refCliente = `${idpedido}-${idlinea}`; + + // Solo mostramos las columnas necesarias (como en el orden de DataTable HTML) + const rowData = [input, refCliente, descripcion, cnt_pedida, precio_compra]; // Llamar backend para validar la fila const result = await validarFila(rowData); @@ -163,7 +176,8 @@ document.addEventListener('DOMContentLoaded', function () { // Actualizar campo "Notas" con el enlace if (skUrl) { - const notasHtml = `Ver presupuesto`; + const skId = result.data?.sk_id ?? ''; + const notasHtml = `Ver presupuesto (${skId})`; // 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 @@ -176,7 +190,7 @@ document.addEventListener('DOMContentLoaded', function () { if (result.price_warning) { html = skUrl ? `La fila se importó exitosamente, pero el precio se ha ajustado debajo de costes.

Ver presupuesto` - : 'La fila se importó exitosamente, pero el precio se ha ajustado debajo de costes.'; + : 'La fila se importó exitosamente, pero el precio se ha ajustado debajo de costes.'; icon = 'warning'; } @@ -284,10 +298,12 @@ document.addEventListener('DOMContentLoaded', function () { idsNoAjustados.push(result.data.sk_id); } + const skId = result.data?.sk_id ?? ''; + if (skUrl) { - fila.rowData[6] = `Ver presupuesto`; + fila.rowData[6] = `Ver presupuesto (${skId})`; } else { - fila.rowData[6] = `Importado`; + fila.rowData[6] = `Importado (${skId})`; } } else { fila.rowData[6] = `${result.message ?? 'Error desconocido'}`; From caac71a48df13821f0614d0c4db2e61014be8ca0 Mon Sep 17 00:00:00 2001 From: amazuecos Date: Mon, 5 May 2025 20:59:57 +0200 Subject: [PATCH 035/127] zip pdf download --- ci4/app/Config/Routes.php | 1 + .../Controllers/Produccion/Ordentrabajo.php | 47 +- ci4/app/Language/es/Produccion.php | 1 + ci4/app/Services/ProductionService.php | 4 + .../vuexy/components/tables/ot_table.php | 3 +- .../form/produccion/viewOrdenTrabajoList.php | 36 +- .../themes/vuexy/pdfs/orden_trabajo_view.php | 407 ++++++++++++++++++ .../components/datatables/otDatatable.js | 118 +++-- .../js/safekat/pages/produccion/index.js | 58 ++- httpdocs/themes/vuexy/css/pdf.ot.css | 7 +- 10 files changed, 605 insertions(+), 77 deletions(-) create mode 100755 ci4/app/Views/themes/vuexy/pdfs/orden_trabajo_view.php diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 5814ccb4..dfdda020 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -804,6 +804,7 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func * PDF *========================**/ $routes->get('pdf/(:num)', 'Ordentrabajo::get_pdf/$1'); + $routes->get('pdf/content/(:num)', 'Ordentrabajo::get_ot_pdf_content/$1'); $routes->get('pdf/ferro/(:num)', 'Ordentrabajo::get_ferro_pdf/$1'); $routes->get('pdf/prototipo/(:num)', 'Ordentrabajo::get_prototipo_pdf/$1'); $routes->get('portada/(:num)', 'Ordentrabajo::get_portada_img/$1'); diff --git a/ci4/app/Controllers/Produccion/Ordentrabajo.php b/ci4/app/Controllers/Produccion/Ordentrabajo.php index 6bb737f7..804fa8ec 100755 --- a/ci4/app/Controllers/Produccion/Ordentrabajo.php +++ b/ci4/app/Controllers/Produccion/Ordentrabajo.php @@ -243,6 +243,7 @@ class Ordentrabajo extends BaseController fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" ) ->add("action", fn($q) => $q->id) + ->add("pdf_check", fn($q) => $q->id) ->toJson(true); } public function datatable_pendientes() @@ -258,6 +259,7 @@ class Ordentrabajo extends BaseController fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" ) ->add("action", fn($q) => $q->id) + ->add("pdf_check", fn($q) => $q->id) ->toJson(true); } public function datatable_ferro_pendiente() @@ -273,6 +275,7 @@ class Ordentrabajo extends BaseController fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" ) ->add("action", fn($q) => $q->id) + ->add("pdf_check", fn($q) => $q->id) ->toJson(true); } public function datatable_ferro_ok() @@ -288,6 +291,7 @@ class Ordentrabajo extends BaseController fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" ) ->add("action", fn($q) => $q->id) + ->add("pdf_check", fn($q) => $q->id) ->toJson(true); } public function datatable_news() @@ -302,6 +306,7 @@ class Ordentrabajo extends BaseController fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" ) ->add("action", fn($q) => $q->id) + ->add("pdf_check", fn($q) => $q->id) ->toJson(true); } public function datatable_prod() @@ -316,6 +321,7 @@ class Ordentrabajo extends BaseController fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" ) ->add("action", fn($q) => $q->id) + ->add("pdf_check", fn($q) => $q->id) ->toJson(true); } public function datatable_waiting() @@ -330,6 +336,7 @@ class Ordentrabajo extends BaseController fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" ) ->add("action", fn($q) => $q->id) + ->add("pdf_check", fn($q) => $q->id) ->toJson(true); } public function datatable_revision_com() @@ -344,6 +351,7 @@ class Ordentrabajo extends BaseController fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : "" ) ->add("action", fn($q) => $q->id) + ->add("pdf_check", fn($q) => $q->id) ->toJson(true); } public function papel_gramaje_datatable() @@ -641,7 +649,7 @@ class Ordentrabajo extends BaseController $this->viewData['ot_tarea'] = $otTareaEntity; $this->viewData['ot'] = $otTareaEntity->orden_trabajo(); $this->viewData['presupuesto'] = $this->viewData['ot']->presupuesto(); - + $this->viewData['impresoras'] = $impresoras; $this->viewData['breadcrumb'] = [ ['title' => lang("Produccion.maquinista.maquinas"), 'route' => route_to("viewProduccionMaquinistaMaquinas"), 'active' => false], @@ -784,8 +792,8 @@ class Ordentrabajo extends BaseController ); $tareaEntity = $this->otTarea->find($tareaId); $tiempo_trabajado = $tareaEntity->tiempo_trabajado(); - $responseData['tiempo_total_estimado']+=$tareaEntity->tiempo_estimado; - $responseData['tiempo_total_real']+=$tiempo_trabajado; + $responseData['tiempo_total_estimado'] += $tareaEntity->tiempo_estimado; + $responseData['tiempo_total_real'] += $tiempo_trabajado; $responseData["estado"] = $validatedData["estado"]; $tareaEntity->tiempo_real = $tiempo_trabajado / count($validatedData['tareas']); $tareaEntity->click_init = $validatedData['click_init'] / count($validatedData['tareas']); @@ -823,7 +831,7 @@ class Ordentrabajo extends BaseController $validatedData = $this->validation->getValidated(); foreach ($validatedData['ordenes_trabajo'] as $key => $orden_trabajo_id) { - $maquinaOtTarea = $this->maquinaOtTareaModel->where('orden_trabajo_id', $orden_trabajo_id)->where('maquina_id', $validatedData['maquina_id'])->where('deleted_at',null)->countAllResults(); + $maquinaOtTarea = $this->maquinaOtTareaModel->where('orden_trabajo_id', $orden_trabajo_id)->where('maquina_id', $validatedData['maquina_id'])->where('deleted_at', null)->countAllResults(); if ($maquinaOtTarea) { continue; } @@ -855,17 +863,15 @@ class Ordentrabajo extends BaseController $tarea->click_init = $bodyData['click_init']; $tarea->click_end = $bodyData['click_end']; $totalTareas[] = $tarea; - } - } foreach ($totalTareas as $key => $tarea) { - $tiempo_trabajado = $tarea->tiempo_trabajado(); - $tarea->tiempo_real = $tiempo_trabajado / count($totalTareas); - $tarea->click_init = $tarea->click_init / count($totalTareas); - $tarea->click_end = $tarea->click_end / count($totalTareas); + $tiempo_trabajado = $tarea->tiempo_trabajado(); + $tarea->tiempo_real = $tiempo_trabajado / count($totalTareas); + $tarea->click_init = $tarea->click_init / count($totalTareas); + $tarea->click_end = $tarea->click_end / count($totalTareas); - $this->otTarea->save($tarea); + $this->otTarea->save($tarea); } if ($estado == "F") { $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->delete(); @@ -875,7 +881,7 @@ class Ordentrabajo extends BaseController } public function delete_maquina_orden_trabajo_tarea($maquina_orden_trabajo_tarea_id) { - + $status = $this->maquinaOtTareaModel->delete($maquina_orden_trabajo_tarea_id); return $this->response->setJSON(["message" => lang("App.user_alert_delete"), "status" => $status]); } @@ -889,7 +895,7 @@ class Ordentrabajo extends BaseController $this->produccionService->deleteOrdenTrabajoTareaProgressDates($tarea->id); } } - $status = $this->maquinaOtTareaModel->where('maquina_id',$maquina_id)->delete(); + $status = $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->delete(); return $this->response->setJSON(["message" => lang("App.user_alert_delete"), "status" => $status]); } @@ -916,23 +922,22 @@ class Ordentrabajo extends BaseController $tareas = $this->produccionService->init($maquina_ot->orden_trabajo_id) ->getTareasWithMaquina($maquina_id, ['P', 'I', 'S', 'D']); foreach ($tareas as $key => $tarea) { - $responseData['tiempo_total_estimado']+= $tarea->tiempo_estimado; - $responseData['tiempo_total_real']+= $tarea->tiempo_real; + $responseData['tiempo_total_estimado'] += $tarea->tiempo_estimado; + $responseData['tiempo_total_real'] += $tarea->tiempo_real; $responseData["estado"] = $tarea->lastState()->estado; - if($tarea->presupuesto_linea_id){ + if ($tarea->presupuesto_linea_id) { $responseData["clicks_total"] += $tarea->presupuesto_linea()->rotativa_clicks_total; $responseData["tirada_total"] += $tarea->orden_trabajo()->presupuesto()->tirada; - } } } $responseData['tiempo_total_estimado'] = float_seconds_to_hhmmss_string($responseData['tiempo_total_estimado']); $responseData['tiempo_total_real'] = float_seconds_to_hhmmss_string($responseData['tiempo_total_real']); return $this->response->setJSON($responseData); - } - public function printPackagingLabels(){ + public function printPackagingLabels() + { $ot_id = $this->request->getPost('ot_id') ?? null; $unidades_caja = $this->request->getPost('unidades_caja') ?? null; @@ -963,4 +968,8 @@ class Ordentrabajo extends BaseController return $this->response->setJSON($result); } + public function get_ot_pdf_content($orden_trabajo_id) + { + return $this->produccionService->init($orden_trabajo_id)->getPdfContent(); + } } diff --git a/ci4/app/Language/es/Produccion.php b/ci4/app/Language/es/Produccion.php index c9c7ddce..90aeda9d 100755 --- a/ci4/app/Language/es/Produccion.php +++ b/ci4/app/Language/es/Produccion.php @@ -1,6 +1,7 @@ "Descargar", "navs" => [ 'finalizadas' => 'Finalizadas', 'pendientes' => 'Pendientes', diff --git a/ci4/app/Services/ProductionService.php b/ci4/app/Services/ProductionService.php index 6091fab0..25679b40 100755 --- a/ci4/app/Services/ProductionService.php +++ b/ci4/app/Services/ProductionService.php @@ -621,6 +621,10 @@ class ProductionService extends BaseService { return view("themes/vuexy/pdfs/orden_trabajo", $this->getDataPdf()); } + public function getPdfContent() + { + return view("themes/vuexy/pdfs/orden_trabajo_view", $this->getDataPdf()); + } public function getFerroPdf() { return view("themes/vuexy/pdfs/ferro", $this->getDataPdf()); diff --git a/ci4/app/Views/themes/vuexy/components/tables/ot_table.php b/ci4/app/Views/themes/vuexy/components/tables/ot_table.php index cc43a4f9..ad280f80 100755 --- a/ci4/app/Views/themes/vuexy/components/tables/ot_table.php +++ b/ci4/app/Views/themes/vuexy/components/tables/ot_table.php @@ -3,7 +3,8 @@ - + + diff --git a/ci4/app/Views/themes/vuexy/form/produccion/viewOrdenTrabajoList.php b/ci4/app/Views/themes/vuexy/form/produccion/viewOrdenTrabajoList.php index d401c3d5..3292a21b 100755 --- a/ci4/app/Views/themes/vuexy/form/produccion/viewOrdenTrabajoList.php +++ b/ci4/app/Views/themes/vuexy/form/produccion/viewOrdenTrabajoList.php @@ -6,41 +6,46 @@ section('content'); ?> -
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + +
IN
PORT.
ACABAD.
ENCUAD.
MANIPUL.
+ + + +
+
+
;color:;"> + +
+
+
+
;color:;"> + papel_impresion()->papel_code_ot ?> +
+
"> + +
+
;color:;"> + papel_impresion()->papel_code_ot ?> +
+
;color:;"> + tarifa()->code : "" ?> +
+ $acabado): ?> + tarifa()->isUVI()): ?> +
;color:white;"> + + tarifa()->code ?> +
+ + +
+
+
"> +
+
+ ;">id ?> +
+
+ barcode +
+ +
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + +
IDSK + +
CLIENTE + alias ?> +
TITULO + titulo ?> +
ISBNisbn ?>
PEDIDO CLIENTEid ?>
+
+
+
+ + + imposicion_esquema()): ?> + imposicion_esquema()->svg_schema ?> + + + +
+
+
+ + + + + +
Imposicionfull_name ?? "" ?>
+
+
+
+
+
+
IMP. INTERIOR
+
+
+ + + + + + + + + + + +
ancho ?>xalto ?> tirada ?> + merma ?> tipo_presupuesto()?->codigo ?? "" ?> lomo_cubierta, 2, ',', '.') ?>
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PáginasEjemplaresTintasFormasMáquinaClicsTiempo
paginas ?> tirada ?> tinta() ?>formas)->formas ?>maquina()->nombre ?>rotativa_clicks_total ?>horas_maquina * 3600) ?>
papel_impresion ?>papel_impresion()->gramaje . " " . "gr" ?> + isRotativa()): ?> + rotativa_metros_total, 2, ',', '.') ?> metros + +
+
+
+
+
+

+ comment_interior ?> +

+
+
+
+
+ +
+
IMP. CUBIERTA
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
TintasEjemplaresMaquinaMarcapaginasTiempo
tinta() ?>tirada ?>maquina()->nombre ?>marcapaginas ? "SI" : "NO" ?>horas_maquina * 3600) ?>
formas)->maquina_ancho ?>xformas)->maquina_alto ?>ancho ?>xalto ?>papel_impresion ?>papel_impresion()->gramaje . " " . "gr" ?>
+
+
+ +
+

+ comment_cubierta ?> +

+
+
+
+ +
+ +
+
ACABADOS/ENCUADERNACIÓN
+
+
;color:;"> + +
+ + $acabado): ?> + + + + + + + + + + + + + + + + + +
Plastificadotarifa()->nombre ?>UVI EXTERNO:proveedor() ? $acabado->proveedor()->nombre : "" ?>
info_solapa_guillotina?>CORTE PIE:
+ + $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 "No se ha podido renderizar la tabla de encuadernación"; + // echo "
$error_message"; + } + } + ?> + 0): ?> + +
+
+
+

+ comment_encuadernacion ?> +

+
+
+ + +
+ +
+
+
LOGISTICA
+
+ + + + + + + + + + + + + +
Peso UnidadPeso PedidoCajasCorte Pie
gr 1000 ? number_format($peso_pedido / 1000, 2, ',', '.') . " kg" : number_format($peso_pedido, 2, ',', '.') . " gr" ?> --
+
+
+ +
+

+ comment_logistica ?> +

+
+
+
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/components/datatables/otDatatable.js b/httpdocs/assets/js/safekat/components/datatables/otDatatable.js index bd736040..d1e1f0b8 100644 --- a/httpdocs/assets/js/safekat/components/datatables/otDatatable.js +++ b/httpdocs/assets/js/safekat/components/datatables/otDatatable.js @@ -12,10 +12,11 @@ class OrdenTrabajoDatatable { this.datatableRevisionComerical = this.item.find("#ot-datatable-revision-com") - + this.columnIdIndex = 1; this.datatableColumns = [ - { data: 'id', searchable: false, sortable: false }, + { data: 'pdf_check', searchable: false, sortable: false, render: d => `` }, + { data: 'id', searchable: false, sortable: true }, { data: 'pedido_id', searchable: false, sortable: false }, { data: 'fecha_encuadernado_at', searchable: false, sortable: false }, { data: 'cliente_nombre', searchable: false, sortable: false }, @@ -51,8 +52,27 @@ class OrdenTrabajoDatatable { } ] } + actualDatatable(event) { + let order = $(event.currentTarget).data('order') + console.log(order) + this.focusDatatable = this.datatableOrder[order] + } + events(){ + this.datatableOrder = [ + this.datatableN, + this.datatableP, + this.datatableW, + this.datatableFP, + this.datatableFO, + this.datatableRC, + this.datatableProduccion, + this.datatable + ] + this.focusDatatable = this.datatableN + $('.nav-link').on('click', this.actualDatatable.bind(this)) + } init() { - this.datatableItem.DataTable({ + this.datatable = this.datatableItem.DataTable({ processing: true, layout: { topStart: 'pageLength', @@ -60,9 +80,10 @@ class OrdenTrabajoDatatable { bottomStart: 'info', bottomEnd: 'paging' }, + order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, - + ], serverSide: true, pageLength: 25, @@ -71,14 +92,14 @@ class OrdenTrabajoDatatable { }, columns: this.datatableColumns, ajax: '/produccion/ordentrabajo/datatable', - createdRow: (row,data,dataIndex) => { - $(row).css("border-left",`10px solid ${data.logo.color}`) - $(row).css("border-right",`10px solid ${data.logo.color}`) + createdRow: (row, data, dataIndex) => { + $(row).css("border-left", `10px solid ${data.logo.color}`) + $(row).css("border-right", `10px solid ${data.logo.color}`) } }); } initPendientes() { - this.datatablePendientesItem.DataTable({ + this.datatableP = this.datatablePendientesItem.DataTable({ processing: true, layout: { topStart: 'pageLength', @@ -86,6 +107,7 @@ class OrdenTrabajoDatatable { bottomStart: 'info', bottomEnd: 'paging' }, + order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, @@ -97,15 +119,15 @@ class OrdenTrabajoDatatable { }, columns: this.datatableColumns, ajax: '/produccion/ordentrabajo/datatable_pendientes', - createdRow: (row,data,dataIndex) => { - $(row).css("border-left",`20px solid ${data.logo.color}`) - $(row).css("border-right",`20px solid ${data.logo.color}`) + createdRow: (row, data, dataIndex) => { + $(row).css("border-left", `20px solid ${data.logo.color}`) + $(row).css("border-right", `20px solid ${data.logo.color}`) } }); } initFerroPendiente() { - this.datatableFerroPendienteItem.DataTable({ + this.datatableFP = this.datatableFerroPendienteItem.DataTable({ processing: true, layout: { topStart: 'pageLength', @@ -115,23 +137,24 @@ class OrdenTrabajoDatatable { }, serverSide: true, pageLength: 25, + order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, - + ], language: { url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" }, columns: this.datatableColumns, ajax: '/produccion/ordentrabajo/datatable_ferro_pendiente', - createdRow: (row,data,dataIndex) => { - $(row).css("border-left",`20px solid ${data.logo.color}`) - $(row).css("border-right",`20px solid ${data.logo.color}`) + createdRow: (row, data, dataIndex) => { + $(row).css("border-left", `20px solid ${data.logo.color}`) + $(row).css("border-right", `20px solid ${data.logo.color}`) } }); } initFerroOk() { - this.datatableFerroOkItem.DataTable({ + this.datatableFO = this.datatableFerroOkItem.DataTable({ processing: true, layout: { topStart: 'pageLength', @@ -140,9 +163,10 @@ class OrdenTrabajoDatatable { bottomEnd: 'paging' }, serverSide: true, + order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, - + ], pageLength: 25, language: { @@ -150,14 +174,14 @@ class OrdenTrabajoDatatable { }, columns: this.datatableColumns, ajax: '/produccion/ordentrabajo/datatable_ferro_ok', - createdRow: (row,data,dataIndex) => { - $(row).css("border-left",`20px solid ${data.logo.color}`) - $(row).css("border-right",`20px solid ${data.logo.color}`) + createdRow: (row, data, dataIndex) => { + $(row).css("border-left", `20px solid ${data.logo.color}`) + $(row).css("border-right", `20px solid ${data.logo.color}`) } }); } initNews() { - this.datatableNews.DataTable({ + this.datatableN = this.datatableNews.DataTable({ processing: true, layout: { topStart: 'pageLength', @@ -166,9 +190,10 @@ class OrdenTrabajoDatatable { bottomEnd: 'paging' }, serverSide: true, + order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, - + ], pageLength: 25, language: { @@ -176,14 +201,16 @@ class OrdenTrabajoDatatable { }, columns: this.datatableColumns, ajax: '/produccion/ordentrabajo/datatable_news', - createdRow: (row,data,dataIndex) => { - $(row).css("border-left",`20px solid ${data.logo.color}`) - $(row).css("border-right",`20px solid ${data.logo.color}`) + createdRow: (row, data, dataIndex) => { + $(row).css("border-left", `20px solid ${data.logo.color}`) + $(row).css("border-right", `20px solid ${data.logo.color}`) } }); + this.focusDatatable = this.datatableN + } initWaiting() { - this.datatableWaiting.DataTable({ + this.datatableW = this.datatableWaiting.DataTable({ processing: true, layout: { topStart: 'pageLength', @@ -192,9 +219,10 @@ class OrdenTrabajoDatatable { bottomEnd: 'paging' }, serverSide: true, + order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, - + ], pageLength: 25, language: { @@ -202,14 +230,14 @@ class OrdenTrabajoDatatable { }, columns: this.datatableColumns, ajax: '/produccion/ordentrabajo/datatable_waiting', - createdRow: (row,data,dataIndex) => { - $(row).css("border-left",`20px solid ${data.logo.color}`) - $(row).css("border-right",`20px solid ${data.logo.color}`) + createdRow: (row, data, dataIndex) => { + $(row).css("border-left", `20px solid ${data.logo.color}`) + $(row).css("border-right", `20px solid ${data.logo.color}`) } }); } initProd() { - this.datatableProd.DataTable({ + this.datatableProduccion = this.datatableProd.DataTable({ processing: true, layout: { topStart: 'pageLength', @@ -218,9 +246,10 @@ class OrdenTrabajoDatatable { bottomEnd: 'paging' }, serverSide: true, + order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, - + ], pageLength: 25, language: { @@ -228,14 +257,14 @@ class OrdenTrabajoDatatable { }, columns: this.datatableColumns, ajax: '/produccion/ordentrabajo/datatable_prod', - createdRow: (row,data,dataIndex) => { - $(row).css("border-left",`20px solid ${data.logo.color}`) - $(row).css("border-right",`20px solid ${data.logo.color}`) + createdRow: (row, data, dataIndex) => { + $(row).css("border-left", `20px solid ${data.logo.color}`) + $(row).css("border-right", `20px solid ${data.logo.color}`) } }); } initRevisionComercial() { - this.datatableRevisionComerical.DataTable({ + this.datatableRC = this.datatableRevisionComerical.DataTable({ processing: true, layout: { topStart: 'pageLength', @@ -244,9 +273,10 @@ class OrdenTrabajoDatatable { bottomEnd: 'paging' }, serverSide: true, + order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, - + ], pageLength: 25, language: { @@ -254,12 +284,18 @@ class OrdenTrabajoDatatable { }, columns: this.datatableColumns, ajax: '/produccion/ordentrabajo/datatable_revision_com', - createdRow: (row,data,dataIndex) => { - $(row).css("border-left",`20px solid ${data.logo.color}`) - $(row).css("border-right",`20px solid ${data.logo.color}`) + createdRow: (row, data, dataIndex) => { + $(row).css("border-left", `20px solid ${data.logo.color}`) + $(row).css("border-right", `20px solid ${data.logo.color}`) } }); } + getSelectIDs() { + return this.focusDatatable.rows((idx, data, node) => { + return $(node).find('input[type="checkbox"]').prop('checked'); + }).data().toArray().map((e) => parseInt(e.id)) + + } } diff --git a/httpdocs/assets/js/safekat/pages/produccion/index.js b/httpdocs/assets/js/safekat/pages/produccion/index.js index e2e0aa59..96c7b795 100644 --- a/httpdocs/assets/js/safekat/pages/produccion/index.js +++ b/httpdocs/assets/js/safekat/pages/produccion/index.js @@ -1,4 +1,6 @@ import OrdenTrabajoDatatable from '../../components/datatables/otDatatable.js' +import Ajax from '../../components/ajax.js' +import { alertError, alertSuccessMessage } from '../../components/alerts/sweetAlert.js' $(function () { const otDatatable = new OrdenTrabajoDatatable($("#ots-datatables-container")) @@ -9,5 +11,59 @@ $(function () { otDatatable.initNews() otDatatable.initProd() otDatatable.initWaiting() + otDatatable.events() // otDatatable.initRevisionComercial() -}) \ No newline at end of file + $("#btn-download-pdf-zip").on('click', async () => { + let zip = new JSZip() + let ordenesTrabajo = otDatatable.getSelectIDs() + for (let element of ordenesTrabajo) { + try { + + // Create hidden iframe + Notiflix.Block.circle('.section-block',{opacity : 1}); + const response = await getPdf(element); + var opt = { + margin: 2, + filename: $(response).find(".pdf-wrapper").data("id") + ".pdf", + image: { type: 'jpeg', quality: 1 }, + html2canvas: { scale: 4, logging: false }, + jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' } + }; + let pdf = await html2pdf().set(opt).from(response).outputPdf('blob'); + zip.file(opt.filename, pdf); + } catch (error) { + } + }; + if (ordenesTrabajo.length > 0) { + + Notiflix.Block.remove('.section-block'); + zip.generateAsync({ type: "blob" }).then(function (blob) { + const now = new Date(); + const pad = (n) => String(n).padStart(2, '0'); + const timestamp = `${now.getFullYear()}_${pad(now.getMonth() + 1)}_${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`; + const filename = `ordenes_trabajo_${timestamp}.zip`; + + const link = document.createElement("a"); + link.href = URL.createObjectURL(blob); + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }); + }else{ + alertError('Seleccione una OT para descargar').fire() + } + + + + + + }) +}) + + +const getPdf = (otId) => { + return new Promise((resolve, reject) => { + new Ajax('/produccion/ordentrabajo/pdf/content/' + otId, null, null, resolve, reject).get() + }) +} diff --git a/httpdocs/themes/vuexy/css/pdf.ot.css b/httpdocs/themes/vuexy/css/pdf.ot.css index 1a4dd39a..3058c604 100644 --- a/httpdocs/themes/vuexy/css/pdf.ot.css +++ b/httpdocs/themes/vuexy/css/pdf.ot.css @@ -3,8 +3,8 @@ margin: 0; } @media print { - body, - html { + .page, + { width: 210mm; height: 297mm; max-width: 210mm; @@ -22,7 +22,8 @@ html { max-height: 297mm; background-color: white; } -body { + +.page { border: 0px solid; padding: 10px; margin : 10px; From 30c5b06d3d818b414f2ba4a4d278cf9e18b0ee35 Mon Sep 17 00:00:00 2001 From: amazuecos Date: Tue, 6 May 2025 08:30:01 +0200 Subject: [PATCH 036/127] update progress based on task time and task date --- ci4/app/Services/ProductionService.php | 65 ++++++++++++++++---------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/ci4/app/Services/ProductionService.php b/ci4/app/Services/ProductionService.php index 25679b40..db2463b8 100755 --- a/ci4/app/Services/ProductionService.php +++ b/ci4/app/Services/ProductionService.php @@ -228,8 +228,8 @@ class ProductionService extends BaseService $this->maquinaModel = model(MaquinaModel::class); $this->otModel = model(OrdenTrabajoModel::class); $ot = $this->otModel->find($orden_trabajo_id); - if($ot == null){ - throw new Exception(lang('Produccion.errors.ot_not_found',['ot_id' => $orden_trabajo_id])); + if ($ot == null) { + throw new Exception(lang('Produccion.errors.ot_not_found', ['ot_id' => $orden_trabajo_id])); } $this->ot = $ot; $pedido = $this->ot->pedido(); @@ -610,11 +610,11 @@ class ProductionService extends BaseService } return ["tareas" => $tareas]; } - public function getTareasWithMaquina(int $maquina_id,?array $tareaEstados = null) : ?array + public function getTareasWithMaquina(int $maquina_id, ?array $tareaEstados = null): ?array { return $this->otModel->queryMaquinaTareas($maquina_id, $tareaEstados) - ->where('ordenes_trabajo.id', $this->ot->id) - ->get()->getResult(OrdenTrabajoTareaEntity::class); + ->where('ordenes_trabajo.id', $this->ot->id) + ->get()->getResult(OrdenTrabajoTareaEntity::class); } public function getPdf() @@ -1439,6 +1439,16 @@ class ProductionService extends BaseService } return $pedidoUserDates; } + public function getTiempoEstimadoTotalTareasSeconds(): int + { + try { + $time_tareas_seconds = array_map(fn($q) => $q->tiempo_estimado ?? 0, $this->ot->tareas()); + $seconds = array_sum($time_tareas_seconds); + return $seconds; + } catch (\Throwable $th) { + return 0; + } + } public function getTiempoProcesamientoHHMMSS(): ?string { try { @@ -1490,33 +1500,31 @@ class ProductionService extends BaseService } return $uvi; } - //TODO ACTUALIZAR + public function updateProgress(): bool { - $userDates = $this->ordenTrabajoConfig->DATE_USER_MAPPING; - $pedidoUserDates = $this->ordenTrabajoConfig->DATE_USER_MAPPING_PEDIDO; - - $fill_dates = 0; - $status = false; - $total = count($userDates) + count($pedidoUserDates); + $progress = $this->getOtProgress(); if ($this->ot->estado != "F") { - if ($this->ot->dates()) { - - foreach ($userDates as $key => $value) { - if ($this->ot->dates()->{$key} != null) $fill_dates++; - } - foreach ($pedidoUserDates as $key => $value) { - if ($this->pedido->{$key} != null) $fill_dates++; - } - - $progreso = (float) $fill_dates / $total * 100; - $status = $this->otModel->update($this->ot->id, ["progreso" => round($progreso, 2)]); - } + $status = $this->otModel->update($this->ot->id, ["progreso" => round($progress, 2)]); } else { $status = $this->otModel->update($this->ot->id, ["progreso" => 100]); } return $status; } + public function getOtProgress() + { + $datesWithTime = $this->getOrdenTrabajoTareaDatesWithTiempoEstimado(); + $tiempo_estimado_total = $this->getTiempoEstimadoTotalTareasSeconds(); + $progress = 0; + $otDates = $this->ot->dates(); + foreach ($datesWithTime as $key => $dateWithTime) { + ["date" => $date, "tiempo_estimado" => $tiempo_estimado] = $dateWithTime; + if ($otDates->{$date}) { + $progress += $tiempo_estimado / $tiempo_estimado_total * 100; + } + } + return $progress; + } public function getOtColorStatus(): string { if ($this->ot->dates()) { @@ -2194,6 +2202,15 @@ class ProductionService extends BaseService } return $data; } + public function getOrdenTrabajoTareaDatesWithTiempoEstimado(): array + { + $dates = []; + foreach ($this->ot->tareas() as $key => $tarea) { + $dates[$tarea->id]["date"] = $this->getOrdenTrabajoTareaDate($tarea); + $dates[$tarea->id]["tiempo_estimado"] = $tarea->tiempo_estimado; + } + return $dates; + } public function getOrdenTrabajoTareaDates(): array { $dates = []; From ddd7c471a1b09cf205199a4c0f48aff5440a76cd Mon Sep 17 00:00:00 2001 From: amazuecos Date: Tue, 6 May 2025 08:40:07 +0200 Subject: [PATCH 037/127] progress ot --- ci4/app/Language/es/Produccion.php | 1 + ci4/app/Services/ProductionService.php | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ci4/app/Language/es/Produccion.php b/ci4/app/Language/es/Produccion.php index 90aeda9d..728920c0 100755 --- a/ci4/app/Language/es/Produccion.php +++ b/ci4/app/Language/es/Produccion.php @@ -119,6 +119,7 @@ return [ //IMPRESION "impresion_bn" => "Impresión BN", "cubierta" => "Cubierta/Portada", + "sobrecubierta" => "Sobrecubierta", "guarda" => "Guarda", "encuadernacion" => "Encuadernación", diff --git a/ci4/app/Services/ProductionService.php b/ci4/app/Services/ProductionService.php index db2463b8..0105df94 100755 --- a/ci4/app/Services/ProductionService.php +++ b/ci4/app/Services/ProductionService.php @@ -1519,8 +1519,13 @@ class ProductionService extends BaseService $otDates = $this->ot->dates(); foreach ($datesWithTime as $key => $dateWithTime) { ["date" => $date, "tiempo_estimado" => $tiempo_estimado] = $dateWithTime; - if ($otDates->{$date}) { - $progress += $tiempo_estimado / $tiempo_estimado_total * 100; + try { + if ($otDates->{$date}) { + $progress += $tiempo_estimado / $tiempo_estimado_total * 100; + } + } catch (\Throwable $th) { + //throw $th; + $progress += 0; } } return $progress; From f6b8d2ba85509a61f25052473da92a4ebb95d431 Mon Sep 17 00:00:00 2001 From: amazuecos Date: Tue, 6 May 2025 10:06:33 +0200 Subject: [PATCH 038/127] columns searching and ordering ots --- .../components/datatables/otDatatable.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/httpdocs/assets/js/safekat/components/datatables/otDatatable.js b/httpdocs/assets/js/safekat/components/datatables/otDatatable.js index d1e1f0b8..527f15f1 100644 --- a/httpdocs/assets/js/safekat/components/datatables/otDatatable.js +++ b/httpdocs/assets/js/safekat/components/datatables/otDatatable.js @@ -16,14 +16,14 @@ class OrdenTrabajoDatatable { this.datatableColumns = [ { data: 'pdf_check', searchable: false, sortable: false, render: d => `` }, - { data: 'id', searchable: false, sortable: true }, - { data: 'pedido_id', searchable: false, sortable: false }, - { data: 'fecha_encuadernado_at', searchable: false, sortable: false }, - { data: 'cliente_nombre', searchable: false, sortable: false }, - { data: 'presupuesto_titulo', searchable: false, sortable: false }, - { data: 'ubicacion_nombre', searchable: false, sortable: false }, - { data: 'total_tirada', searchable: false, sortable: false, render: (d) => `${d}` }, - { data: 'tipo_presupuesto_impresion', searchable: false, sortable: false }, + { data: 'id', searchable: true, sortable: true }, + { data: 'pedido_id', searchable: true, sortable: true }, + { data: 'fecha_encuadernado_at',name:"pedidos.fecha_encuadernado", searchable: true, sortable: true }, + { data: 'cliente_nombre', name:"clientes.nombre", searchable: true, sortable: false }, + { data: 'presupuesto_titulo', name:"presupuestos.titulo", searchable: true, sortable: true }, + { data: 'ubicacion_nombre', name:"ubicaciones.nombre", searchable: true, sortable: true }, + { data: 'total_tirada', name:"pedidos.total_tirada",searchable: true, sortable: true, render: (d) => `${d}` }, + { data: 'tipo_presupuesto_impresion', name:"tipos_presupuestos.codigo", searchable: true, sortable: true }, { data: 'logo', searchable: false, sortable: false, render: (d, t) => { return `
@@ -33,7 +33,7 @@ class OrdenTrabajoDatatable { } }, { - data: 'progreso', searchable: false, sortable: false, render: (d, t) => { + data: 'progreso',name:"ordenes_trabajo.progreso", searchable: false, sortable: true, render: (d, t) => { return `
${d}%
From 8b340b76d3b99914c07c987af4748bf8ff1c4b82 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Tue, 6 May 2025 10:17:33 +0200 Subject: [PATCH 039/127] =?UTF-8?q?A=C3=B1adidos=20IDs=20de=20los=20usuari?= =?UTF-8?q?os=20creador=20y=20actualizador=20al=20guardar=20desde=20presup?= =?UTF-8?q?uesto=20cliente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci4/app/Models/Presupuestos/PresupuestoModel.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ci4/app/Models/Presupuestos/PresupuestoModel.php b/ci4/app/Models/Presupuestos/PresupuestoModel.php index c57aa1c0..04699831 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoModel.php @@ -508,15 +508,17 @@ class PresupuestoModel extends \App\Models\BaseModel 'excluir_rotativa' => $excluir_rotativa, ]; + /* Actualizacion */ if ($id != 0) { $fields['id'] = $id; $fields['updated_at'] = date('Y-m-d H:i:s', now()); - } - - if ($id != 0) { + $fields['user_update_id'] = auth()->id(); $this->db->table($this->table)->where('id', $id)->update($fields); return $id; - } else { + } + /* Inserccion */ + else { + $fields['user_created_id'] = auth()->id(); $this->db->table($this->table)->insert($fields); return $this->db->insertID(); } From 20594bd44c0ee555e971697e26afd06184aca26e Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Tue, 6 May 2025 10:55:21 +0200 Subject: [PATCH 040/127] Al crear un presupuesto hay que fijar el user_update_id. FIXED --- ci4/app/Models/Presupuestos/PresupuestoModel.php | 1 + 1 file changed, 1 insertion(+) diff --git a/ci4/app/Models/Presupuestos/PresupuestoModel.php b/ci4/app/Models/Presupuestos/PresupuestoModel.php index 04699831..9b6a137f 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoModel.php @@ -519,6 +519,7 @@ class PresupuestoModel extends \App\Models\BaseModel /* Inserccion */ else { $fields['user_created_id'] = auth()->id(); + $fields['user_update_id'] = auth()->id(); $this->db->table($this->table)->insert($fields); return $this->db->insertID(); } From cab7bc3daf555feba535b6784c7d3dad1dd9f585 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Tue, 6 May 2025 12:09:54 +0200 Subject: [PATCH 041/127] Arreglado bug en listado de comerciales en vista diferente al buscador de presupuestos --- ci4/app/Models/Presupuestos/PresupuestoModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci4/app/Models/Presupuestos/PresupuestoModel.php b/ci4/app/Models/Presupuestos/PresupuestoModel.php index 9b6a137f..d2cf953d 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoModel.php @@ -271,7 +271,7 @@ class PresupuestoModel extends \App\Models\BaseModel t1.total_presupuesto AS total_presupuesto, t1.total_presupuesto AS total_presupuesto, t6.estado AS estado" ); $builder->join("clientes t2", "t1.cliente_id = t2.id", "left"); - $builder->join("users t3", "t1.user_update_id = t3.id", "left"); + $builder->join("users t3", "t2.comercial_id = t3.id", "left"); $builder->join("lg_paises t5", "t1.pais_id = t5.id", "left"); $builder->join("presupuesto_estados t6", "t1.estado_id = t6.id", "left"); From d3dd18a156d3140b4840e9498545a57ab85f6e88 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Tue, 6 May 2025 12:23:00 +0200 Subject: [PATCH 042/127] Expuestos campos ID y PrecioTonelada en visualizacion de papeles de impresion --- .../Configuracion/PapelImpresionModel.php | 32 ++++++++++--------- .../papel/viewPapelImpresionList.php | 8 +++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/ci4/app/Models/Configuracion/PapelImpresionModel.php b/ci4/app/Models/Configuracion/PapelImpresionModel.php index fc03ccae..d816b9c6 100755 --- a/ci4/app/Models/Configuracion/PapelImpresionModel.php +++ b/ci4/app/Models/Configuracion/PapelImpresionModel.php @@ -13,20 +13,22 @@ class PapelImpresionModel extends \App\Models\BaseModel protected $useAutoIncrement = true; const SORTABLE = [ - 0 => "t1.nombre", - 1 => "t2.nombre", - 2 => "t1.gramaje", - 3 => "t1.interior", - 4 => "t1.bn", - 5 => "t1.color", - 6 => "t1.cubierta", - 7 => "t1.use_for_tapa_dura", - 8 => "t1.sobrecubierta", - 9 => "t1.guardas", - 10 => "t1.inkjet", - 11 => "t1.rotativa", - 12 => "t1.isActivo", - 13 => "t1.use_in_client", + 0 => "t1.id", + 1 => "t1.nombre", + 2 => "t2.nombre", + 3 => "t1.gramaje", + 4 => "t1.interior", + 5 => "t1.bn", + 6 => "t1.color", + 7 => "t1.cubierta", + 8 => "t1.use_for_tapa_dura", + 9 => "t1.sobrecubierta", + 10 => "t1.guardas", + 11 => "t1.inkjet", + 12 => "t1.rotativa", + 13 => "t1.isActivo", + 14 => "t1.use_in_client", + 15 => "t1.precio_tonelada", ]; @@ -173,7 +175,7 @@ class PapelImpresionModel extends \App\Models\BaseModel ->groupStart() ->like("t1.nombre", $search) ->orLike("t1.gramaje", $search) - ->orLike("t1.nombre", $search) + ->orLike("t1.precio_tonelada", $search) ->orLike("t1.gramaje", $search) ->orLike("t2.nombre", $search) ->groupEnd(); diff --git a/ci4/app/Views/themes/vuexy/form/configuracion/papel/viewPapelImpresionList.php b/ci4/app/Views/themes/vuexy/form/configuracion/papel/viewPapelImpresionList.php index 3702621a..f3f41f75 100755 --- a/ci4/app/Views/themes/vuexy/form/configuracion/papel/viewPapelImpresionList.php +++ b/ci4/app/Views/themes/vuexy/form/configuracion/papel/viewPapelImpresionList.php @@ -18,6 +18,7 @@ + @@ -32,6 +33,7 @@ + @@ -80,7 +82,7 @@ } ], stateSave: true, - order: [[1, 'asc']], + order: [[2, 'asc']], language: { url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" }, @@ -98,6 +100,7 @@ } ], columns : [ + { 'data': 'id' }, { 'data': 'nombre' }, { 'data': 'papel_generico_id' }, { 'data': 'gramaje', render : (d) => `${d}`}, @@ -112,13 +115,14 @@ { 'data': 'rotativa' }, { 'data': 'isActivo' }, { 'data': 'use_in_client' }, + { 'data': 'precio_tonelada' }, { 'data': actionBtns } ] }); theTable.on( 'draw.dt', function () { - const boolCols = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; + const boolCols = [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; for (let coln of boolCols) { theTable.column(coln, { page: 'current' }).nodes().each( function (cell, i) { cell.innerHTML = cell.innerHTML == '1' ? '' : ''; From eeba76b124014472f78835c8bc36e660deb33094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 6 May 2025 12:28:03 +0200 Subject: [PATCH 043/127] arreglado servicios de encuadernacion --- .../PresupuestoEncuadernacionesModel.php | 93 +++++++++++++++---- .../Tarifas/TarifaEncuadernacionModel.php | 4 +- .../presupuestoAdmin/sections/resumen.js | 4 +- .../presupuestoAdmin/sections/servicios.js | 6 +- 4 files changed, 83 insertions(+), 24 deletions(-) diff --git a/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php b/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php index 44614da1..8f5d52cb 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php @@ -86,6 +86,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel 'tarifa_nombre' => $tarifa_proveedor->tarifa_enc_nombre, 'nombre' => $tarifa_proveedor->tarifa_enc_nombre, 'precio_unidad' => $result_data[0], + 'importe_fijo' => $tarifa_proveedor->importe_fijo, 'tiempo' => $tiempo, 'total' => $result_data[1], 'precio_total' => $result_data[1], @@ -124,6 +125,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel 'nombre' => $tarifa['tarifa_nombre'], 'proveedor' => lang('Presupuestos.no_disponible'), 'precio_unidad' => 0, + 'importe_fijo' => 0, 'tiempo' => null, 'total' => 0, 'precio_total' => 0, @@ -143,6 +145,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel 'tarifa_nombre' => $tarifa_proveedor->tarifa_enc_nombre, 'nombre' => $tarifa_proveedor->tarifa_enc_nombre, 'precio_unidad' => $result_data[0], + 'importe_fijo' => $tarifa_proveedor->importe_fijo, 'tiempo' => null, 'total' => $result_data[1], 'precio_total' => $result_data[1], @@ -170,6 +173,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel 'nombre' => $tarifa['tarifa_nombre'], 'proveedor' => lang('Presupuestos.no_disponible'), 'precio_unidad' => 0, + 'importe_fijo' => 0, 'tiempo' => null, 'total' => 0, 'precio_total' => 0, @@ -228,6 +232,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel array_push($ret_array, (object) [ 'tarifa_id' => $tarifa->tarifa_enc_id, 'tarifa_nombre' => $tarifa->tarifa_enc_nombre, + 'importe_fijo' => $tarifa->importe_fijo, 'nombre' => $tarifa->tarifa_enc_nombre, 'precio_unidad' => $result_data[0], 'tiempo' => null, @@ -254,6 +259,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel 'nombre' => $modelTarifa->getNombreTarifaEncuadernacion($tarifa_encuadernacion_id)[0]->nombre, 'proveedor' => lang('Presupuestos.no_disponible'), 'precio_unidad' => 0, + 'importe_fijo' => 0, 'tiempo' => null, 'total' => 0, 'precio_total' => 0, @@ -309,6 +315,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel 'precio_unidad' => $result_data[0], 'tiempo' => $tiempo, 'paginas_por_cuadernillo' => $paginas_cuadernillo, + 'importe_fijo' => $tarifa_proveedor->importe_fijo, 'precio_total' => $result_data[1], 'total' => $result_data[1], 'margen' => $result_data[2], @@ -334,6 +341,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel 'nombre' => $modelTarifa->getNombreTarifaEncuadernacion($tarifa_encuadernacion_id)[0]->nombre, 'proveedor' => lang('Presupuestos.no_disponible'), 'precio_unidad' => 0, + 'importe_fijo' => 0, 'tiempo' => null, 'paginas_por_cuadernillo' => null, 'total' => 0, @@ -351,16 +359,17 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel $precio_unidad = floatval($tarifa->precio_max) - (floatval($tarifa->precio_max) - floatval($tarifa->precio_min)) / ($tarifa->paginas_max - $tarifa->paginas_min) * ($paginas - $tarifa->paginas_min); if ($paginas > $tarifa->paginas_max) $precio_unidad = $tarifa->precio_max; - $precio_unidad = $precio_unidad * (1 + floatval($tarifa->margen) / 100.0); - - if (!$is_POD) { - $precio_unidad += floatval($tarifa->tarifa_importe_fijo) / floatval($ejemplares); - } + $precio_unidad = $precio_unidad * (1 + floatval($tarifa->margen)/100.0); $precio_unidad = round($precio_unidad, 2); $total = $precio_unidad * $ejemplares; $margen = floatval($tarifa->margen); + if (!$is_POD) { + $total += floatval($tarifa->tarifa_importe_fijo) ; + $precio_unidad = round(floatval($total / $ejemplares), 2); + } + $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); if ($tarifa_precio_min > $total) { @@ -459,18 +468,66 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel */ public function getResource($presupuesto_id = -1) { - $builder = $this->db - ->table($this->table . " t1") - ->select( - "t1.id AS id, t1.tarifa_encuadernado_id AS tarifa_encuadernado_id, t1.precio_unidad AS precio_unidad, t1.tiempo AS tiempo, - t1.precio_total AS precio_total, t1.margen AS margen, t2.nombre AS nombre, t1.proveedor_id AS proveedor_id, t3.nombre AS proveedor, - t1.paginas_por_cuadernillo AS paginas_por_cuadernillo" - ); - - $builder->where('t1.presupuesto_id', $presupuesto_id); - $builder->join("tarifa_encuadernacion t2", "t1.tarifa_encuadernado_id = t2.id", "left"); - $builder->join("lg_proveedores t3", "t1.proveedor_id = t3.id", "left"); - + + $builder = $this->db->table('presupuesto_encuadernaciones t1') + ->select(" + t1.id AS id, + t1.tarifa_encuadernado_id AS tarifa_encuadernado_id, + t1.precio_unidad AS precio_unidad, + t1.tiempo AS tiempo, + t1.precio_total AS precio_total, + t1.margen AS margen, + t2.nombre AS nombre, + t1.proveedor_id AS proveedor_id, + t3.nombre AS proveedor, + t1.paginas_por_cuadernillo AS paginas_por_cuadernillo, + presupuestos.tirada AS tirada, + CASE + WHEN t2.por_horas = 0 THEN ( + SELECT t2_sub.importe_fijo + FROM tarifa_encuadernacion_tiradas t2_sub + JOIN tarifa_encuadernacion_lineas t3_sub ON t2_sub.id = t3_sub.tirada_encuadernacion_id + JOIN tarifa_encuadernacion_dimensiones t4_sub ON t3_sub.dimensiones_id = t4_sub.id + WHERE t2_sub.tarifa_encuadernacion_id = t1.tarifa_encuadernado_id + AND t2_sub.tirada_min <= presupuestos.tirada + AND t2_sub.tirada_max >= presupuestos.tirada + AND t3_sub.paginas_libro_min <= presupuestos.paginas + AND t3_sub.paginas_libro_max >= presupuestos.paginas + AND t4_sub.ancho_min <= + CASE WHEN presupuestos.papel_formato_personalizado = 1 THEN LEAST(presupuestos.papel_formato_ancho, presupuestos.papel_formato_alto) + ELSE LEAST(lg_papel_formato.ancho, lg_papel_formato.alto) END + AND t4_sub.ancho_max > + CASE WHEN presupuestos.papel_formato_personalizado = 1 THEN LEAST(presupuestos.papel_formato_ancho, presupuestos.papel_formato_alto) + ELSE LEAST(lg_papel_formato.ancho, lg_papel_formato.alto) END + AND t4_sub.alto_min <= + CASE WHEN presupuestos.papel_formato_personalizado = 1 THEN GREATEST(presupuestos.papel_formato_ancho, presupuestos.papel_formato_alto) + ELSE GREATEST(lg_papel_formato.ancho, lg_papel_formato.alto) END + AND t4_sub.alto_max >= + CASE WHEN presupuestos.papel_formato_personalizado = 1 THEN GREATEST(presupuestos.papel_formato_ancho, presupuestos.papel_formato_alto) + ELSE GREATEST(lg_papel_formato.ancho, lg_papel_formato.alto) END + AND t2_sub.proveedor_id = t1.proveedor_id + LIMIT 1 + ) + WHEN t2.por_horas = 1 THEN ( + SELECT t2_sub.importe_fijo + FROM tarifa_encuadernacion_tiradas t2_sub + JOIN tarifa_encuadernacion_lineas_horas t3_sub ON t2_sub.id = t3_sub.tirada_encuadernacion_id + WHERE t2_sub.tarifa_encuadernacion_id = t1.tarifa_encuadernado_id + AND t2_sub.tirada_min <= presupuestos.tirada + AND t2_sub.tirada_max > presupuestos.tirada + AND t3_sub.tiempo_min <= t1.tiempo + AND t3_sub.tiempo_max > t1.tiempo + AND t2_sub.proveedor_id = t1.proveedor_id + LIMIT 1 + ) + ELSE NULL + END AS importe_fijo + ") + ->join("tarifa_encuadernacion t2", "t1.tarifa_encuadernado_id = t2.id", "left") + ->join("lg_proveedores t3", "t1.proveedor_id = t3.id", "left") + ->join("presupuestos", "presupuestos.id = t1.presupuesto_id", "left") + ->join("lg_papel_formato", "lg_papel_formato.id = presupuestos.papel_formato_id", "left") + ->where("t1.presupuesto_id", $presupuesto_id); return $builder; } @@ -486,7 +543,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel return 0.01; else return $temp; - + } private function calcularTiempoCosido($maquina_id, $paginas, $tirada, $cuadernillos_por_pagina = 32) diff --git a/ci4/app/Models/Tarifas/TarifaEncuadernacionModel.php b/ci4/app/Models/Tarifas/TarifaEncuadernacionModel.php index 9cf03991..8680d628 100755 --- a/ci4/app/Models/Tarifas/TarifaEncuadernacionModel.php +++ b/ci4/app/Models/Tarifas/TarifaEncuadernacionModel.php @@ -127,7 +127,7 @@ class TarifaEncuadernacionModel extends \App\Models\BaseModel $builder = $this->db ->table($this->table . " t1") ->select( - "t1.id AS tarifa_enc_id, t1.nombre AS tarifa_enc_nombre, t3.total_min AS tarifa_precio_min, t2.importe_fijo AS tarifa_importe_fijo, + "t1.id AS tarifa_enc_id, t1.nombre AS tarifa_enc_nombre, t3.total_min AS tarifa_precio_min, t2.importe_fijo AS tarifa_importe_fijo, t2.importe_fijo AS importe_fijo, t2.id AS tarifa_tirada_id, t2.proveedor_id AS proveedor_id, t5.nombre AS proveedor_nombre, t2.tirada_min AS tirada_min, t2.tirada_max AS tirada_max, t3.id AS tarifa_linea_id, t3.paginas_libro_min AS paginas_min, t3.paginas_libro_max AS paginas_max, t3.precio_min AS precio_min, t3.precio_max AS precio_max, t3.margen AS margen, t4.ancho_min AS ancho_min, t4.ancho_max AS ancho_max, t4.alto_min AS alto_min, t4.alto_max AS alto_max" @@ -166,7 +166,7 @@ class TarifaEncuadernacionModel extends \App\Models\BaseModel $builder = $this->db ->table($this->table . " t1") ->select( - "t1.id AS tarifa_enc_id, t1.nombre AS tarifa_enc_nombre, t3.total_min AS tarifa_precio_min, t2.importe_fijo AS tarifa_importe_fijo, + "t1.id AS tarifa_enc_id, t1.nombre AS tarifa_enc_nombre, t3.total_min AS tarifa_precio_min, t2.importe_fijo AS tarifa_importe_fijo, t2.importe_fijo AS importe_fijo, t2.id AS tarifa_tirada_id, t2.proveedor_id AS proveedor_id, t5.nombre AS proveedor_nombre, t2.tirada_min AS tirada_min, t2.tirada_max AS tirada_max, t3.id AS tarifa_linea_id, t3.tiempo_min AS tiempo_min, t3.tiempo_max AS tiempo_max, t3.precio_hora AS precio_hora, t3.margen AS margen" ) diff --git a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/resumen.js b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/resumen.js index 2bf7c8c5..cf35b450 100644 --- a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/resumen.js +++ b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/resumen.js @@ -212,9 +212,9 @@ class Resumen { let rowData = this.data(); let total_servicio = self.roundToTwoDecimals(parseFloat(rowData.precio_total)); let margen_servicio = parseFloat(rowData.margen); + let importe_fijo = parseFloat(rowData.importe_fijo); totalServicios += total_servicio - let base = self.roundToTwoDecimals(total_servicio / (1 + margen_servicio / 100.0)); - base = self.roundToTwoDecimals(base / total) * total; + let base = self.roundToTwoDecimals((total_servicio-importe_fijo) / (1 + margen_servicio / 100.0)); margenServicios += self.roundToTwoDecimals(parseFloat(total_servicio - base)); }); } diff --git a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/servicios.js b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/servicios.js index e58b2d91..216a173b 100644 --- a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/servicios.js +++ b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/servicios.js @@ -1026,7 +1026,8 @@ class ServiciosEncuadernacion { }, { data: 'precio_unidad', render: function (data, type, row) { - let precio_unidad_coste = (row.precio_unidad / (1 + row.margen / 100)).toFixed(2); + const precio_total_sin_fijo = (row.precio_unidad*parseInt($('#tirada').val()))-parseFloat(row.importe_fijo); + let precio_unidad_coste = ((precio_total_sin_fijo / parseInt($('#tirada').val())) / (1 + row.margen / 100)).toFixed(2); precio_unidad_coste = parseFloat(precio_unidad_coste).toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const precio_unidad = parseFloat(row.precio_unidad).toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); return precio_unidad_coste + '/' + precio_unidad; @@ -1048,7 +1049,8 @@ class ServiciosEncuadernacion { `; } - } + }, + {data: 'importe_fijo', visible: false}, ], drawCallback: function (settings) { From 89e6d0787a9d7880183515b1d0f1481cedb8c6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 6 May 2025 13:06:48 +0200 Subject: [PATCH 044/127] puesto como precio minimo el coste --- .../Presupuestos/PresupuestoAcabadosModel.php | 14 +++++++------- .../PresupuestoEncuadernacionesModel.php | 14 +++++++------- .../Presupuestos/PresupuestoManipuladosModel.php | 16 +++++++--------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php b/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php index 562c40fc..36565374 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php @@ -305,17 +305,17 @@ class PresupuestoAcabadosModel extends \App\Models\BaseModel $precio_unidad = $tarifa->precio_max; $precio_unidad = $precio_unidad * (1 + floatval($tarifa->margen) / 100.0); - if (!$is_POD) { - $precio_unidad += floatval($tarifa->tarifa_importe_fijo)/floatval($tirada); - } - $total = $precio_unidad * $tirada; $margen = floatval($tarifa->margen); + $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); if ($tarifa->tarifa_precio_min > $total) { - $total = $total - ($total * $margen / 100.0); - $margen = round(100.0 * (floatval($tarifa->tarifa_precio_min) - $total) / floatval($tarifa->tarifa_precio_min), 0); - $total = floatval($tarifa->tarifa_precio_min); + $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); + $precio_unidad = round(floatval($total / $tirada), 2); + } + + if (!$is_POD) { + $total += floatval($tarifa->tarifa_importe_fijo) ; $precio_unidad = round(floatval($total / $tirada), 2); } diff --git a/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php b/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php index 8f5d52cb..da89b13c 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php @@ -365,17 +365,17 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel $total = $precio_unidad * $ejemplares; $margen = floatval($tarifa->margen); - if (!$is_POD) { - $total += floatval($tarifa->tarifa_importe_fijo) ; - $precio_unidad = round(floatval($total / $ejemplares), 2); - } $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); if ($tarifa_precio_min > $total) { - $total = $total - ($total * $margen / 100.0); - $margen = round(100.0 * (floatval($tarifa_precio_min) - $total) / floatval($tarifa_precio_min), 0); - $total = floatval($tarifa_precio_min); + + $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); + $precio_unidad = round(floatval($total / $ejemplares), 2); + + } + if (!$is_POD) { + $total += floatval($tarifa->tarifa_importe_fijo) ; $precio_unidad = round(floatval($total / $ejemplares), 2); } diff --git a/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php b/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php index 9e0637a9..7f221226 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php @@ -102,17 +102,15 @@ class PresupuestoManipuladosModel extends \App\Models\BaseModel $precio_unidad = $tarifa->precio_max; $precio_unidad = $precio_unidad * (1 + floatval($tarifa->margen) / 100.0); - if (!$is_POD) { - $precio_unidad += floatval($tarifa->tarifa_importe_fijo)/floatval($tirada); - } - $total = $precio_unidad * $tirada; $margen = floatval($tarifa->margen); - - if ($tarifa->tarifa_precio_min > $total) { - $total = $total - ($total * $margen / 100.0); - $margen = round(100.0 * (floatval($tarifa->tarifa_precio_min) - $total) / floatval($tarifa->tarifa_precio_min), 0); - $total = floatval($tarifa->tarifa_precio_min); + $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); + if ($tarifa_precio_min > $total) { + $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); + $precio_unidad = round(floatval($total / $tirada), 2); + } + if (!$is_POD) { + $total += floatval($tarifa->tarifa_importe_fijo); $precio_unidad = round(floatval($total / $tirada), 2); } From 1a1f5947a0e2b628e4125207eb115dd86e534f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 6 May 2025 13:11:31 +0200 Subject: [PATCH 045/127] arreglado --- ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php | 2 +- .../Models/Presupuestos/PresupuestoEncuadernacionesModel.php | 2 +- ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php b/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php index 36565374..dc646527 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php @@ -309,7 +309,7 @@ class PresupuestoAcabadosModel extends \App\Models\BaseModel $margen = floatval($tarifa->margen); $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); - if ($tarifa->tarifa_precio_min > $total) { + if ($tarifa_precio_min * (1 + floatval($tarifa->margen) / 100.0) > $total) { $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); $precio_unidad = round(floatval($total / $tirada), 2); } diff --git a/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php b/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php index da89b13c..b8bbf45d 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php @@ -368,7 +368,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); - if ($tarifa_precio_min > $total) { + if ($tarifa_precio_min * (1 + floatval($tarifa->margen) / 100.0) > $total) { $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); $precio_unidad = round(floatval($total / $ejemplares), 2); diff --git a/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php b/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php index 7f221226..26873bcd 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php @@ -105,7 +105,7 @@ class PresupuestoManipuladosModel extends \App\Models\BaseModel $total = $precio_unidad * $tirada; $margen = floatval($tarifa->margen); $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); - if ($tarifa_precio_min > $total) { + if ($tarifa_precio_min * (1 + floatval($tarifa->margen) / 100.0) > $total) { $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); $precio_unidad = round(floatval($total / $tirada), 2); } From 89bcd0bda19492d42f303e1cabd584634470fa07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 6 May 2025 13:20:48 +0200 Subject: [PATCH 046/127] resuelto --- ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php | 2 +- .../Models/Presupuestos/PresupuestoEncuadernacionesModel.php | 2 +- ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php b/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php index dc646527..91541f0d 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoAcabadosModel.php @@ -310,7 +310,7 @@ class PresupuestoAcabadosModel extends \App\Models\BaseModel $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); if ($tarifa_precio_min * (1 + floatval($tarifa->margen) / 100.0) > $total) { - $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); + $total = $tarifa_precio_min * (1 + floatval($tarifa->margen)/100.0); $precio_unidad = round(floatval($total / $tirada), 2); } diff --git a/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php b/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php index b8bbf45d..ea73f682 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoEncuadernacionesModel.php @@ -370,7 +370,7 @@ class PresupuestoEncuadernacionesModel extends \App\Models\BaseModel if ($tarifa_precio_min * (1 + floatval($tarifa->margen) / 100.0) > $total) { - $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); + $total = $tarifa_precio_min * (1 + floatval($tarifa->margen)/100.0); $precio_unidad = round(floatval($total / $ejemplares), 2); } diff --git a/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php b/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php index 26873bcd..f33c8e32 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoManipuladosModel.php @@ -106,7 +106,7 @@ class PresupuestoManipuladosModel extends \App\Models\BaseModel $margen = floatval($tarifa->margen); $tarifa_precio_min = floatval($tarifa->tarifa_precio_min); if ($tarifa_precio_min * (1 + floatval($tarifa->margen) / 100.0) > $total) { - $total = $tarifa_precio_min + (1 + floatval($tarifa->margen)/100.0); + $total = $tarifa_precio_min * (1 + floatval($tarifa->margen)/100.0); $precio_unidad = round(floatval($total / $tirada), 2); } if (!$is_POD) { From 15227998aaff1d2d9ed7f532a4b8b1e7b6c64e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 6 May 2025 14:00:03 +0200 Subject: [PATCH 047/127] =?UTF-8?q?cuando=20se=20a=C3=B1ade=20m=C3=A1s=20d?= =?UTF-8?q?e=20una=20direccion=20y=20tiene=20el=20cliente=20marcado=20que?= =?UTF-8?q?=20no=20tenga=20envio=20base,=20se=20suman=20las=20dos=20direcc?= =?UTF-8?q?iones=20al=20presupuesto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../js/safekat/pages/presupuestoAdmin/sections/resumen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/resumen.js b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/resumen.js index cf35b450..3999c4ce 100644 --- a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/resumen.js +++ b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/resumen.js @@ -290,7 +290,7 @@ class Resumen { if (typeof $('#tableOfDireccionesEnvio').DataTable() !== 'undefined' && $('#tableOfDireccionesEnvio').DataTable().rows().count() > 0) { $('#tableOfDireccionesEnvio').DataTable().rows().every(function (rowIdx, tableLoop, rowLoop) { // el primer envio es el base, y no se debe de cobrar - if (rowIdx != 0) { + if (rowIdx != 0 || (rowIdx == 0 && $('#noEnvioBase').val() == 1)) { let data = this.data() totalEnvios += parseFloat(data.precio) From efef0c0199ee629550842614b85a83c47744bbd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 6 May 2025 14:20:25 +0200 Subject: [PATCH 048/127] arraglado --- httpdocs/assets/js/safekat/pages/cliente/cliente.js | 2 +- .../js/safekat/pages/presupuestoAdmin/presupuestoAdminAdd.js | 2 +- .../safekat/pages/presupuestoAdmin/sections/datosGenerales.js | 2 +- .../assets/js/safekat/pages/presupuestoAdmin/sections/envios.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/httpdocs/assets/js/safekat/pages/cliente/cliente.js b/httpdocs/assets/js/safekat/pages/cliente/cliente.js index adca3242..51eba6a1 100644 --- a/httpdocs/assets/js/safekat/pages/cliente/cliente.js +++ b/httpdocs/assets/js/safekat/pages/cliente/cliente.js @@ -13,7 +13,7 @@ class Cliente { this.tarifas = new tarifasClienteView($('#tarifascliente')); - this.pais = new ClassSelect($("#paisId"), '/paises/menuitems2', "Seleccione un país", {[this.csrf_token]: this.csrf_hash}); + this.pais = new ClassSelect($("#paisId"), '/configuracion/paises/menuitems2', "Seleccione un país", {[this.csrf_token]: this.csrf_hash}); this.soporte = new ClassSelect($("#soporteId"), '/users/getMenuComerciales', "Seleccione un usuario", {[this.csrf_token]: this.csrf_hash}); this.comercial = new ClassSelect($("#comercialId"), '/users/getMenuComerciales', "Seleccione un usuario", {[this.csrf_token]: this.csrf_hash}); this.formaPago = new ClassSelect($("#formaPagoId"), '/formas-pago/menuitems', "Seleccione una forma de pago", {[this.csrf_token]: this.csrf_hash}); diff --git a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/presupuestoAdminAdd.js b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/presupuestoAdminAdd.js index d911e1dc..5d4e7b9f 100644 --- a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/presupuestoAdminAdd.js +++ b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/presupuestoAdminAdd.js @@ -11,7 +11,7 @@ class PresupuestoAdminAdd { this.inc_rei = $('#incRei'); this.cliente = new ClassSelect($('#clienteId'), '/clientes/cliente/getSelect2', 'Seleccione cliente'); - this.pais = new ClassSelect($('#paisId'), '/paises/menuitems2', 'Seleccione País'); + this.pais = new ClassSelect($('#paisId'), '/configuracion/paises/menuitems2', 'Seleccione País'); this.fecha = $('#updated_at'); this.estado = $('#estado_id'); diff --git a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/datosGenerales.js b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/datosGenerales.js index 7adf940f..1f5063e6 100644 --- a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/datosGenerales.js +++ b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/datosGenerales.js @@ -18,7 +18,7 @@ class DatosGenerales{ this.cliente = new ClassSelect($('#clienteId'), '/clientes/cliente/getSelect2', 'Seleccione cliente'); - this.pais = new ClassSelect($('#paisId'), '/paises/menuitems2', 'Seleccione País'); + this.pais = new ClassSelect($('#paisId'), '/configuracion/paises/menuitems2', 'Seleccione País'); this.referenciaCliente = this.domItem.find('#referenciaCliente'); } diff --git a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/envios.js b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/envios.js index 86c22c82..78f9a81c 100644 --- a/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/envios.js +++ b/httpdocs/assets/js/safekat/pages/presupuestoAdmin/sections/envios.js @@ -15,7 +15,7 @@ class Envios { this.table = null; this.direccionesClienteForm = new ClassSelect($('#add_clientedAdd'), '/misdirecciones/getSelect2', 'Seleccione una direccion', false, {}); - this.paisesClienteForm = new ClassSelect($('#add_pais_id'), '/paises/menuitems2', 'Seleccione país', false, {}); + this.paisesClienteForm = new ClassSelect($('#add_pais_id'), '/configuracion/paises/menuitems2', 'Seleccione país', false, {}); this.modalYesNo = null; this.insertarEnvio = $('#insertar_direccion'); From 528f117c7c0826da17c446f94572058157ea89c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 6 May 2025 16:04:25 +0200 Subject: [PATCH 049/127] terminado --- ci4/app/Views/themes/vuexy/form/soporte/viewTicketForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci4/app/Views/themes/vuexy/form/soporte/viewTicketForm.php b/ci4/app/Views/themes/vuexy/form/soporte/viewTicketForm.php index 43f76678..785c45a4 100755 --- a/ci4/app/Views/themes/vuexy/form/soporte/viewTicketForm.php +++ b/ci4/app/Views/themes/vuexy/form/soporte/viewTicketForm.php @@ -102,7 +102,7 @@
+ value="usuario_ticket) ?>">
From 85318aa10ea6e4332691c3be2a9d0ffe22f1b7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 6 May 2025 16:18:32 +0200 Subject: [PATCH 050/127] terminado --- .../Controllers/Presupuestos/Presupuestocliente.php | 10 ++++++++++ ci4/app/Services/PresupuestoClienteService.php | 8 ++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php index 9abe57a5..50813759 100755 --- a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php +++ b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php @@ -340,6 +340,10 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController if ($tirada[0] <= $POD && $cliente->forzar_rotativa_pod) { $forzarRotativa = true; } + else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) { + $excluirRotativa = true; + } + $input_data = array( 'uso' => 'interior', @@ -768,6 +772,9 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController if ($tirada[0] <= $POD && $cliente->forzar_rotativa_pod) { $forzarRotativa = true; } + else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) { + $excluirRotativa = true; + } $input_data = array( 'uso' => 'interior', @@ -2088,6 +2095,9 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController if ($tirada[$t] <= $POD && $cliente->forzar_rotativa_pod) { $forzarRotativa = true; } + else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) { + $excluirRotativa = true; + } $input_data = array( 'uso' => 'interior', diff --git a/ci4/app/Services/PresupuestoClienteService.php b/ci4/app/Services/PresupuestoClienteService.php index 21dc68d1..bb702918 100755 --- a/ci4/app/Services/PresupuestoClienteService.php +++ b/ci4/app/Services/PresupuestoClienteService.php @@ -13,11 +13,15 @@ class PresupuestoClienteService extends BaseService { public static function obtenerInterior($data) { + $POD = model('App\Models\Configuracion\ConfigVariableModel')->getVariable('POD')->value; + $tirada = $data['datosPedido']->tirada; + + $isPoD = $POD >= $tirada; $rotativa = []; $plana = []; - // no se busca en plana cuando es estándar (no Premium) - if ($data['isHq']) + // no se busca en plana cuando es estándar (no Premium) excepto cuando es PoD + if ($data['isHq'] || $isPoD) $plana = PresupuestoClienteService::obtenerPresupuestoClienteInterior($data); if (!$data['excluirRotativa'] && !$data['isHq']) $rotativa = PresupuestoClienteService::obtenerPresupuestoClienteInteriorRotativa($data); From ff7ed8f594815720168d2fd7e63a71e18e7621ec Mon Sep 17 00:00:00 2001 From: imnavajas Date: Wed, 7 May 2025 11:51:52 +0200 Subject: [PATCH 051/127] Creados scripts --- .../ERP Safekat 2.0 - Papeles Impresion.xlsx | Bin 0 -> 23525 bytes scripts/papeles_impresion/Tramos papel.xlsx | Bin 0 -> 19669 bytes .../loadMargenesPapelImpresion.py | 95 ++++++++++++++++++ .../papeles_impresion/updatePrecioTonelada.py | 58 +++++++++++ 4 files changed, 153 insertions(+) create mode 100644 scripts/papeles_impresion/ERP Safekat 2.0 - Papeles Impresion.xlsx create mode 100644 scripts/papeles_impresion/Tramos papel.xlsx create mode 100644 scripts/papeles_impresion/loadMargenesPapelImpresion.py create mode 100644 scripts/papeles_impresion/updatePrecioTonelada.py diff --git a/scripts/papeles_impresion/ERP Safekat 2.0 - Papeles Impresion.xlsx b/scripts/papeles_impresion/ERP Safekat 2.0 - Papeles Impresion.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..17e6259289db48ec31e48867a8b7d7519bffd668 GIT binary patch literal 23525 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 bJNe&pqJ;^VGP(c&J>`s|EYs!=->&`u?s?y* literal 0 HcmV?d00001 diff --git a/scripts/papeles_impresion/Tramos papel.xlsx b/scripts/papeles_impresion/Tramos papel.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..29c801117b6fc28f83b3e785fa4ec80a9bf030db GIT binary patch literal 19669 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 literal 0 HcmV?d00001 diff --git a/scripts/papeles_impresion/loadMargenesPapelImpresion.py b/scripts/papeles_impresion/loadMargenesPapelImpresion.py new file mode 100644 index 00000000..a4ab9f5f --- /dev/null +++ b/scripts/papeles_impresion/loadMargenesPapelImpresion.py @@ -0,0 +1,95 @@ +import pandas as pd +import mysql.connector + +""" +Script para insertar márgenes en la tabla 'papel_impresion_margenes' en base a un archivo Excel. + +- Lee los papeles objetivo desde la hoja 'Papeles'. +- Lee los tramos de márgenes desde la hoja 'Tramos'. +- Elimina márgenes existentes de los papeles especificados. +- Inserta nuevos tramos de márgenes para cada papel. + +Requiere: +- Archivo Excel con hojas 'Papeles' y 'Tramos'. +- Conexión activa a la base de datos MySQL. +- Paquetes: pandas, mysql-connector-python + +Autor: IMN +Fecha: 07/05/2025 +""" + +# === CONFIGURACIÓN === +RUTA_EXCEL = "Tramos papel.xlsx" +DB_CONFIG = { + "host": "82.223.102.252", + "user": "erp-dev", + "password": "Txhn75@10", + "database": "erp-dev" +} + +# === CARGAR DATOS DESDE EXCEL === +df_papeles = pd.read_excel(RUTA_EXCEL, sheet_name="Papeles") +df_tramos = pd.read_excel(RUTA_EXCEL, sheet_name="Tramos") + +ids_papeles = df_papeles['ID'].dropna().astype(int).unique().tolist() +print("IDs de papeles cargados:", ids_papeles) + +# === CONEXIÓN A MYSQL === +conn = mysql.connector.connect(**DB_CONFIG) +cursor = conn.cursor() + +# === ELIMINAR MÁRGENES EXISTENTES === +delete_query = f""" +DELETE FROM papel_impresion_margenes +WHERE papel_impresion_id IN ({', '.join(map(str, ids_papeles))}); +""" +cursor.execute(delete_query) +print(f"Eliminadas entradas antiguas para {len(ids_papeles)} papeles.") + +# === ACTUALIZAR PRECIO TONELADA PARA CADA PAPEL === +update_query = """ +UPDATE lg_papel_impresion +SET precio_tonelada = %s +WHERE id = %s +""" + +# Preparar los valores (precio, id) +updates = [] +for _, row in df_papeles.iterrows(): + papel_id = int(row["ID"]) + precio = float(row["Precio Tonelada"]) + updates.append((precio, papel_id)) + +# Ejecutar actualizaciones +cursor.executemany(update_query, updates) +conn.commit() +print(f"Actualizados {cursor.rowcount} precios en lg_papel_impresion.") + +# === PREPARAR DATOS NUEVOS === +insert_query = """ +INSERT INTO papel_impresion_margenes ( + papel_impresion_id, paginas_min, paginas_max, margen, + user_created_id, user_updated_id, is_deleted, deleted_at, + created_at, updated_at +) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW()) +""" + +data = [] +for papel_id in ids_papeles: + for _, row in df_tramos.iterrows(): + data.append(( + papel_id, + int(row["Páginas min"]), + int(row["Páginas máx"]), + float(row["%"]), + 10, 10, 0, None + )) + +# === INSERTAR NUEVOS REGISTROS === +cursor.executemany(insert_query, data) +conn.commit() + +# === FINALIZAR === +print(f"Insertadas {cursor.rowcount} filas.") +cursor.close() +conn.close() diff --git a/scripts/papeles_impresion/updatePrecioTonelada.py b/scripts/papeles_impresion/updatePrecioTonelada.py new file mode 100644 index 00000000..531105dc --- /dev/null +++ b/scripts/papeles_impresion/updatePrecioTonelada.py @@ -0,0 +1,58 @@ +import pandas as pd +import mysql.connector + +""" +Script para actualizar la columna 'precio_tonelada' en la tabla 'lg_papel_impresion' desde un archivo Excel. + +- Lee los valores de ID y Precio desde un archivo Excel con cabecera clara. +- Conecta a la base de datos y actualiza los precios de tonelada para los IDs especificados. + +Requiere: +- Archivo Excel con columnas 'ID' y 'Precio Tonelada'. +- Conexión activa a la base de datos MySQL. +- Paquetes: pandas, mysql-connector-python + +Autor: IMN +Fecha: 07/05/2025 +""" + +# === CONFIGURACIÓN DE LA BASE DE DATOS === +DB_CONFIG = { + "host": "82.223.102.252", + "user": "erp-dev", + "password": "Txhn75@10", + "database": "erp-dev" +} + +# === CARGAR DATOS DESDE EXCEL === +df = pd.read_excel("ERP Safekat 2.0 - Papeles Impresion.xlsx") + +# === CONEXIÓN A MYSQL === +conn = mysql.connector.connect(**DB_CONFIG) +cursor = conn.cursor() + +# === CONSULTA DE ACTUALIZACIÓN === +update_query = """ +UPDATE lg_papel_impresion +SET precio_tonelada = %s +WHERE id = %s +""" + +# === PREPARAR DATOS === +data = [] +for _, row in df.iterrows(): + try: + papel_id = int(row['ID']) + precio = float(row['Precio Tonelada']) + data.append((precio, papel_id)) + except (ValueError, TypeError): + continue # Ignorar datos inválidos + +# === EJECUTAR ACTUALIZACIONES === +cursor.executemany(update_query, data) +conn.commit() +print(f"✅ Actualizados {cursor.rowcount} registros en lg_papel_impresion.") + +# === CERRAR CONEXIÓN === +cursor.close() +conn.close() From 5d228cc10ca1eac5b8f03254e455b4e217c34881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Thu, 8 May 2025 13:18:33 +0200 Subject: [PATCH 052/127] corregido --- ci4/app/Controllers/Presupuestos/Presupuestocliente.php | 2 +- ci4/app/Models/Configuracion/PapelGenericoModel.php | 2 +- ci4/app/Services/PresupuestoService.php | 4 ++++ .../js/safekat/pages/importadorPresupuestos/importador.js | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php index 50813759..5db5ad6b 100755 --- a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php +++ b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php @@ -1347,7 +1347,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController $datos_presupuesto['entrega_taller'] = $reqData['entrega_taller'] ?? 0; - $resultado_presupuesto['info']['merma'] = $resultado_presupuesto['info']['num_formas'] ? + $resultado_presupuesto['info']['merma'] = isset($resultado_presupuesto['info']['num_formas']) ? PresupuestoService::calcular_merma($selected_tirada, $POD, $resultado_presupuesto['info']['num_formas']): PresupuestoService::calcular_merma($selected_tirada, $POD); $datos_presupuesto['faja'] = $faja; diff --git a/ci4/app/Models/Configuracion/PapelGenericoModel.php b/ci4/app/Models/Configuracion/PapelGenericoModel.php index 118dadf2..d4a18445 100755 --- a/ci4/app/Models/Configuracion/PapelGenericoModel.php +++ b/ci4/app/Models/Configuracion/PapelGenericoModel.php @@ -433,7 +433,7 @@ class PapelGenericoModel extends \App\Models\BaseModel 4.-> papeles genericos que aparecen en esos papeles impresion */ - if ($POD == true && ($tipo == 'color' || $tipo == 'negro')) { + if ($POD == true && ($tipo == 'color')) { if ($tipo == 'color') $tipo = 'colorhq'; else if ($tipo == 'negro') diff --git a/ci4/app/Services/PresupuestoService.php b/ci4/app/Services/PresupuestoService.php index c8aa7d05..b2871e58 100755 --- a/ci4/app/Services/PresupuestoService.php +++ b/ci4/app/Services/PresupuestoService.php @@ -1785,6 +1785,8 @@ class PresupuestoService extends BaseService options: $opciones_papel ); + #$query = model("App\Models\Configuracion\PapelImpresionModel")->db->getLastQuery(); + $lineas = array(); // Para cada papel, se obtienen las maquinas disponibles foreach ($papeles as $papel) { @@ -1798,6 +1800,8 @@ class PresupuestoService extends BaseService papel_impresion_id: $papel->id, )->orderBy("t1.id", "asc")->get()->getResultObject(); + $query = model("App\Models\Configuracion\PapelImpresionModel")->db->getLastQuery(); + // Se recorren las máquinas y se calcula el coste de linea por cada una foreach ($maquinas as $maquina) { diff --git a/httpdocs/assets/js/safekat/pages/importadorPresupuestos/importador.js b/httpdocs/assets/js/safekat/pages/importadorPresupuestos/importador.js index f629f293..9415f224 100644 --- a/httpdocs/assets/js/safekat/pages/importadorPresupuestos/importador.js +++ b/httpdocs/assets/js/safekat/pages/importadorPresupuestos/importador.js @@ -344,6 +344,7 @@ class Importador { $('#tamanio').removeClass('d-none'); $('#formatoPersonalizado').addClass('d-none'); $('#papelFormatoPersonalizado').prop('checked', false); + $('#tamanio').empty(); $('#tamanio').append(''); $('#tamanio').val(data.datosGenerales.papel_formato_id).trigger('change'); } From f4ef87456876893cf195be300bd542c8bc7136f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Thu, 8 May 2025 20:16:40 +0200 Subject: [PATCH 053/127] =?UTF-8?q?a=C3=B1adido=20cambio=20de=20calidad=20?= =?UTF-8?q?en=20importador=20erp=20antiguo.=20falta=20a=C3=B1adirlo=20a=20?= =?UTF-8?q?rama=20y=20bubok?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presupuestos/Importadorpresupuestos.php | 9 +++ .../Presupuestos/Presupuestocliente.php | 16 +--- ...-190000_CreateSelectorCalidadImpresion.php | 76 +++++++++++++++++++ .../Seeds/SelectorCalidadImpresionSeeder.php | 55 ++++++++++++++ .../SelectorCalidadImpresion.php | 28 +++++++ .../SelectorCalidadImpresionModel.php | 71 +++++++++++++++++ .../Models/Presupuestos/ImportadorModel.php | 2 +- ci4/app/Services/PresupuestoService.php | 11 +++ 8 files changed, 254 insertions(+), 14 deletions(-) create mode 100755 ci4/app/Database/Migrations/2025-05-08-190000_CreateSelectorCalidadImpresion.php create mode 100644 ci4/app/Database/Seeds/SelectorCalidadImpresionSeeder.php create mode 100644 ci4/app/Entities/Configuracion/SelectorCalidadImpresion.php create mode 100644 ci4/app/Models/Configuracion/SelectorCalidadImpresionModel.php diff --git a/ci4/app/Controllers/Presupuestos/Importadorpresupuestos.php b/ci4/app/Controllers/Presupuestos/Importadorpresupuestos.php index 1974e6b8..5d78d9df 100755 --- a/ci4/app/Controllers/Presupuestos/Importadorpresupuestos.php +++ b/ci4/app/Controllers/Presupuestos/Importadorpresupuestos.php @@ -4,6 +4,7 @@ namespace App\Controllers\Presupuestos; use App\Models\Presupuestos\ImportadorModel; use App\Models\Clientes\ClienteModel; +use App\Services\PresupuestoService; use stdClass; class Importadorpresupuestos extends \App\Controllers\BaseResourceController @@ -484,6 +485,14 @@ class Importadorpresupuestos extends \App\Controllers\BaseResourceController $isColor = true; } + // se recalcula isColor y isHq + [$isColor, $isHq] = PresupuestoService::getCalidad( + 'admin', + null, + $isColor, + $isHq, + intval($this->request->getPost('tirada') ?? 0)); + $tapaCubierta = model('App\Models\Configuracion\TipoPresupuestoModel')-> select("is_tapa_dura")->where('id', $tipo_presupuesto_id)->first(); $tapaCubierta = $tapaCubierta->is_tapa_dura == 0 ? "tapaBlanda" : "tapaDura"; diff --git a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php index 5db5ad6b..41395737 100755 --- a/ci4/app/Controllers/Presupuestos/Presupuestocliente.php +++ b/ci4/app/Controllers/Presupuestos/Presupuestocliente.php @@ -332,10 +332,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController $cliente_model = model(('App\Models\Clientes\ClienteModel')); $cliente = $cliente_model->find($cliente_id); - // Para POD siempre es HQ - if ($tirada[0] <= $POD && $isColor && !$cliente->forzar_rotativa_pod) { - $isHq = true; - } + $forzarRotativa = false; if ($tirada[0] <= $POD && $cliente->forzar_rotativa_pod) { $forzarRotativa = true; @@ -467,7 +464,6 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController //$reqData = $this->request->getPost(); $modelPapelGenerico = new PapelGenericoModel(); - $id = $reqData['id'] ?? 0; $cliente_id = $reqData['clienteId'] ?? -1; @@ -764,10 +760,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController $cliente_model = model(('App\Models\Clientes\ClienteModel')); $cliente = $cliente_model->find($cliente_id); - // Para POD siempre es HQ cuando es color - if ($tirada[0] <= $POD && $isColor && !$cliente->forzar_rotativa_pod) { - $isHq = true; - } + $forzarRotativa = false; if ($tirada[0] <= $POD && $cliente->forzar_rotativa_pod) { $forzarRotativa = true; @@ -2087,10 +2080,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController $cliente_model = model(('App\Models\Clientes\ClienteModel')); $cliente = $cliente_model->find($cliente_id); - // Para POD siempre es HQ - if ($tirada[$t] <= $POD && $isColor && !$cliente->forzar_rotativa_pod) { - $isHq = true; - } + $forzarRotativa = false; if ($tirada[$t] <= $POD && $cliente->forzar_rotativa_pod) { $forzarRotativa = true; diff --git a/ci4/app/Database/Migrations/2025-05-08-190000_CreateSelectorCalidadImpresion.php b/ci4/app/Database/Migrations/2025-05-08-190000_CreateSelectorCalidadImpresion.php new file mode 100755 index 00000000..ab484ab4 --- /dev/null +++ b/ci4/app/Database/Migrations/2025-05-08-190000_CreateSelectorCalidadImpresion.php @@ -0,0 +1,76 @@ +forge->addField([ + 'id' => [ + 'type' => 'INT', + 'constraint' => 11, + 'unsigned' => true, + 'auto_increment' => true, + ], + 'alias' => [ + 'type' => 'VARCHAR', + 'constraint' => 255, + ], + 'cliente_id' => [ + 'type' => 'INT', + 'constraint' => 10, + 'unsigned' => true, + 'null' => true, + ], + 'isPod' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + ], + 'input_isColor' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + ], + 'input_isHq' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + ], + 'output_isColor' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + ], + 'output_isHq' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + ], + 'created_at' => [ + 'type' => 'DATETIME', + 'null' => true, + ], + 'updated_at' => [ + 'type' => 'DATETIME', + 'null' => true, + ], + 'deleted_at' => [ + 'type' => 'DATETIME', + 'null' => true, + ], + ]); + + $this->forge->addKey('id', true); + $this->forge->addForeignKey('cliente_id', 'clientes', 'id', 'CASCADE', 'SET NULL'); + $this->forge->createTable('selector_calidad_impresion'); + } + + public function down() + { + $this->forge->dropTable('selector_calidad_impresion'); + } +} diff --git a/ci4/app/Database/Seeds/SelectorCalidadImpresionSeeder.php b/ci4/app/Database/Seeds/SelectorCalidadImpresionSeeder.php new file mode 100644 index 00000000..e647115b --- /dev/null +++ b/ci4/app/Database/Seeds/SelectorCalidadImpresionSeeder.php @@ -0,0 +1,55 @@ + 'admin', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 0, 'input_isHq' => 0, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'admin', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 1, 'input_isHq' => 0, 'output_isColor' => 1, 'output_isHq' => 0], + ['alias' => 'admin', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 0, 'input_isHq' => 1, 'output_isColor' => 0, 'output_isHq' => 1], + ['alias' => 'admin', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 1, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 1], + ['alias' => 'admin', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 0, 'input_isHq' => 0, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'admin', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 1, 'input_isHq' => 0, 'output_isColor' => 1, 'output_isHq' => 0], + ['alias' => 'admin', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 0, 'input_isHq' => 1, 'output_isColor' => 0, 'output_isHq' => 1], + ['alias' => 'admin', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 1, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 1], + + // cliente + ['alias' => 'cliente', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 0, 'input_isHq' => 0, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'cliente', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 1, 'input_isHq' => 0, 'output_isColor' => 1, 'output_isHq' => 0], + ['alias' => 'cliente', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 0, 'input_isHq' => 1, 'output_isColor' => 0, 'output_isHq' => 1], + ['alias' => 'cliente', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 1, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 1], + ['alias' => 'cliente', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 0, 'input_isHq' => 0, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'cliente', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 1, 'input_isHq' => 0, 'output_isColor' => 1, 'output_isHq' => 0], + ['alias' => 'cliente', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 0, 'input_isHq' => 1, 'output_isColor' => 0, 'output_isHq' => 1], + ['alias' => 'cliente', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 1, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 1], + + // importador-rama + ['alias' => 'importador-rama', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 0, 'input_isHq' => 0, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'importador-rama', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 1, 'input_isHq' => 0, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'importador-rama', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 0, 'input_isHq' => 1, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'importador-rama', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 1, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 0], + ['alias' => 'importador-rama', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 0, 'input_isHq' => 0, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'importador-rama', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 1, 'input_isHq' => 0, 'output_isColor' => 1, 'output_isHq' => 0], + ['alias' => 'importador-rama', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 0, 'input_isHq' => 1, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'importador-rama', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 1, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 0], + + // importador-bubok + ['alias' => 'importador-bubok', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 0, 'input_isHq' => 0, 'output_isColor' => 0, 'output_isHq' => 0], + ['alias' => 'importador-bubok', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 1, 'input_isHq' => 0, 'output_isColor' => 1, 'output_isHq' => 1], + ['alias' => 'importador-bubok', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 0, 'input_isHq' => 1, 'output_isColor' => 0, 'output_isHq' => 1], + ['alias' => 'importador-bubok', 'cliente_id' => null, 'isPod' => 0, 'input_isColor' => 1, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 1], + ['alias' => 'importador-bubok', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 0, 'input_isHq' => 0, 'output_isColor' => 1, 'output_isHq' => 1], + ['alias' => 'importador-bubok', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 1, 'input_isHq' => 0, 'output_isColor' => 1, 'output_isHq' => 1], + ['alias' => 'importador-bubok', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 0, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 1], + ['alias' => 'importador-bubok', 'cliente_id' => null, 'isPod' => 1, 'input_isColor' => 1, 'input_isHq' => 1, 'output_isColor' => 1, 'output_isHq' => 1], + ]; + + $this->db->table('selector_calidad_impresion')->insertBatch($registros); + } +} diff --git a/ci4/app/Entities/Configuracion/SelectorCalidadImpresion.php b/ci4/app/Entities/Configuracion/SelectorCalidadImpresion.php new file mode 100644 index 00000000..c5dabbac --- /dev/null +++ b/ci4/app/Entities/Configuracion/SelectorCalidadImpresion.php @@ -0,0 +1,28 @@ + null, + 'cliente_id' => null, + 'isPod' => 0, + 'input_isColor' => 0, + 'input_isHq' => 0, + 'output_isColor' => 0, + 'output_isHq' => 0, + ]; + + protected $datamap = []; + protected $dates = ['created_at', 'updated_at', 'deleted_at']; + protected $casts = [ + 'isPod' => 'boolean', + 'input_isColor' => 'boolean', + 'input_isHq' => 'boolean', + 'output_isColor' => 'boolean', + 'output_isHq' => 'boolean', + ]; +} diff --git a/ci4/app/Models/Configuracion/SelectorCalidadImpresionModel.php b/ci4/app/Models/Configuracion/SelectorCalidadImpresionModel.php new file mode 100644 index 00000000..f0d54847 --- /dev/null +++ b/ci4/app/Models/Configuracion/SelectorCalidadImpresionModel.php @@ -0,0 +1,71 @@ +getVariable('POD')->value); + $isPoD = $tirada <= $pod ? 1 : 0; + $builder = $this->db + ->table($this->table . " t1") + ->select('output_isColor, output_isHq') + ->where('alias', $alias) + ->where('input_isColor', $isColor) + ->where('input_isHq', $isHq) + ->where('isPod', $isPoD) + ->where('deleted_at', null); + if ($cliente_id) { + $builder->where('cliente_id', $cliente_id); + } + + $output_isColor = 0; + $output_isHq = 0; + + $result = $builder->get()->getRowArray(); + if ($result){ + $output_isColor = $result['output_isColor']; + $output_isHq = $result['output_isHq']; + + return [ + 'status' => true, + 'isColor' => $output_isColor, + 'isHq' => $output_isHq, + ]; + } else { + return [ + 'status' => false, + 'isColor' => $output_isColor, + 'isHq' => $output_isHq, + ]; + } + } + +} diff --git a/ci4/app/Models/Presupuestos/ImportadorModel.php b/ci4/app/Models/Presupuestos/ImportadorModel.php index 76d01904..0a0a6ab5 100755 --- a/ci4/app/Models/Presupuestos/ImportadorModel.php +++ b/ci4/app/Models/Presupuestos/ImportadorModel.php @@ -41,7 +41,7 @@ class ImportadorModel extends \App\Models\BaseModel $db = \Config\Database::connect($this->DBGroup); // Conectar a olderp $builder = $db->table('pedido_libro t1') - ->select('t1.paginas, t1.tirada, t1.papel_formato_personalizado, + ->select('t1.paginas, t1.tirada, t1.papel_formato_personalizado, t1.customer_id, t1.papel_formato_ancho as papel_formato_personalizado_ancho, t1.papel_formato_alto as papel_formato_personalizado_alto, t2.ancho as papel_formato_ancho, t2.alto as papel_formato_alto, diff --git a/ci4/app/Services/PresupuestoService.php b/ci4/app/Services/PresupuestoService.php index b2871e58..a6a80356 100755 --- a/ci4/app/Services/PresupuestoService.php +++ b/ci4/app/Services/PresupuestoService.php @@ -2076,4 +2076,15 @@ class PresupuestoService extends BaseService return round($merma, 0); } + + + public static function getCalidad($alias, $cliente_id, $isColor, $isHq, $tirada) + { + $model = model('App\Models\Configuracion\SelectorCalidadImpresionModel'); + $calidad = $model->getCalidadImpresion($alias, $cliente_id, $isColor, $isHq, $tirada); + if ($calidad) { + return [$calidad['isColor'], $calidad['isHq']]; + } + return null; + } } From 79dc8ca71386c5214d33408502f201ac740d80f2 Mon Sep 17 00:00:00 2001 From: imnavajas Date: Thu, 8 May 2025 22:07:26 +0200 Subject: [PATCH 054/127] =?UTF-8?q?A=C3=B1adida=20tarifa=20hardcoded?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/sftp.json | 7 +- .../Importadores/ImportadorCatalogo.php | 113 +++++++++++++++++- .../importadores/catalogo/catalogo_tool.js | 6 +- 3 files changed, 119 insertions(+), 7 deletions(-) diff --git a/.vscode/sftp.json b/.vscode/sftp.json index 89ef7722..e3778a2f 100755 --- a/.vscode/sftp.json +++ b/.vscode/sftp.json @@ -24,10 +24,15 @@ "username": "sk-dev", "password": "KXvYsubai9v*g61~" }, - "prod":{ + "sk-prod":{ "host": "erp.safekat.es", "username": "erp-demo", "password": "lNkEyukTc1~*3yy9" + }, + "sk-dev":{ + "host": "erp-dev.safekat.es", + "username": "erp-dev", + "password": "snqyxNZIhg8m3!9~" } } diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php index c77b0fea..8e196f83 100644 --- a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php +++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php @@ -132,12 +132,10 @@ class ImportadorCatalogo extends BaseResourceController ]); } - // Mapear cada columna a una variable + // Mapear cada columna a una variable (debe coincidir con catalogo_tool.js) $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([ @@ -146,6 +144,17 @@ class ImportadorCatalogo extends BaseResourceController ]); } + // 0. Comprobar duplicado en tabla de presupuestos + $presupuestoModel = new PresupuestoModel(); // Usa el modelo real que corresponda + $yaExiste = $presupuestoModel->where('referencia_cliente', $refCliente)->first(); + + if ($yaExiste) { + return $this->response->setJSON([ + 'success' => false, + 'message' => 'Referencia ya importada' + ]); + } + $catalogoModel = new CatalogoLibroModel(); // 1. Buscar por ISBN exacto @@ -270,6 +279,32 @@ class ImportadorCatalogo extends BaseResourceController 'data' => $dataToImport ]);*/ + $tarifas = $this->obtenerTarifas(); + $precioDesdeTarifa = $this->calcularPrecioDesdeTarifa( + $dataToImport['isColor'], + $libro->encuadernacion_id, + $libro->ancho, + $libro->alto, + $libro->paginas, + $tarifas + ); + + if (is_null($precioDesdeTarifa)) { + return $this->response->setJSON([ + 'success' => false, + 'message' => 'No se pudo calcular el precio desde las tarifas disponibles.', + 'detalle' => [ + 'tinta' => $dataToImport['isColor'] ? 'color' : 'negro', + 'encuadernacion_id' => $libro->encuadernacion_id, + 'ancho' => $libro->ancho, + 'alto' => $libro->alto, + 'paginas' => $libro->paginas + ] + ]); + } + + // Usar precio calculado + $precio_compra = $precioDesdeTarifa; // Procedemos a intentar guardar el presupuesto // Instancia de presupuesto cliente @@ -332,6 +367,78 @@ class ImportadorCatalogo extends BaseResourceController } + private function calcularPrecioDesdeTarifa($isColor, $encuadernacionId, $ancho, $alto, $paginas, $tarifas) + { + // Solo aplicamos tarifa si la encuadernación es Rústica Fresada (id = 2) + if ((int) $encuadernacionId !== 2) { + return null; + } + + $tinta = $isColor ? 'color' : 'negro'; + + foreach ($tarifas as $tarifa) { + if ( + strtolower($tarifa['tinta']) === $tinta && + strtolower($tarifa['manipulado']) === 'rústica fresada' && + (int) $tarifa['ancho'] === (int) $ancho && + (int) $tarifa['alto'] === (int) $alto + ) { + return round($tarifa['precio_fijo'] + ($tarifa['precio_variable'] * $paginas), 4); + } + } + + return null; // No se encontró tarifa válida + } + + + private function obtenerTarifas() + { + return [ + [ + 'tinta' => 'color', + 'manipulado' => 'Rústica Fresada', + 'ancho' => 200, + 'alto' => 245, + 'precio_fijo' => 1.15, + 'precio_variable' => 0.076 + ], + [ + 'tinta' => 'negro', + 'manipulado' => 'Rústica Fresada', + 'ancho' => 200, + 'alto' => 245, + 'precio_fijo' => 1.15, + 'precio_variable' => 0.009724 + ], + [ + 'tinta' => 'color', + 'manipulado' => 'Rústica Fresada', + 'ancho' => 150, + 'alto' => 210, + 'precio_fijo' => 1.15, + 'precio_variable' => 0.03217 + ], + [ + 'tinta' => 'negro', + 'manipulado' => 'Rústica Fresada', + 'ancho' => 150, + 'alto' => 210, + 'precio_fijo' => 1.15, + 'precio_variable' => 0.00572 + ], + [ + 'tinta' => 'negro', + 'manipulado' => 'Rústica Fresada', + 'ancho' => 170, + 'alto' => 240, + 'precio_fijo' => 1.15, + 'precio_variable' => 0.008 + ] + ]; + } + + + diff --git a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js index 4423e5c5..cf169fce 100644 --- a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js +++ b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js @@ -173,10 +173,10 @@ document.addEventListener('DOMContentLoaded', function () { if (response.ok && result.status === 200) { const skUrl = result.data?.sk_url?.replace('presupuestocliente', 'presupuestoadmin') ?? null; + const skId = result.data?.sk_id ?? ''; // Actualizar campo "Notas" con el enlace - if (skUrl) { - const skId = result.data?.sk_id ?? ''; + if (skUrl) { const notasHtml = `Ver presupuesto (${skId})`; // La columna de notas es la posición 6 (índice 6) rowData[6] = notasHtml; @@ -184,7 +184,7 @@ document.addEventListener('DOMContentLoaded', function () { } let html = skUrl - ? `La fila se importó exitosamente.

Ver presupuesto` + ? `La fila se importó exitosamente.

Ver presupuesto (${skId})` : 'La fila se importó exitosamente.'; let icon = 'success'; From 0a9d1ef68d9a4fdf49777a3fd8c87bc0c72d16b6 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Thu, 8 May 2025 22:10:01 +0200 Subject: [PATCH 055/127] Redondeo de precio tarifa a 2 decimales --- ci4/app/Controllers/Importadores/ImportadorCatalogo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php index 8e196f83..89ef6e06 100644 --- a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php +++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php @@ -383,7 +383,7 @@ class ImportadorCatalogo extends BaseResourceController (int) $tarifa['ancho'] === (int) $ancho && (int) $tarifa['alto'] === (int) $alto ) { - return round($tarifa['precio_fijo'] + ($tarifa['precio_variable'] * $paginas), 4); + return round($tarifa['precio_fijo'] + ($tarifa['precio_variable'] * $paginas), 2); } } From 36a2740eb78dd0010c1f456482c3d193be930109 Mon Sep 17 00:00:00 2001 From: imnavajas Date: Fri, 9 May 2025 12:32:07 +0200 Subject: [PATCH 056/127] =?UTF-8?q?A=C3=B1adido=20selector=20de=20calidad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Importadores/ImportadorCatalogo.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php index 89ef6e06..ca13df60 100644 --- a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php +++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php @@ -223,6 +223,15 @@ class ImportadorCatalogo extends BaseResourceController $sobrecubierta['acabado'] = $libro->sobrecubierta_acabado_id; } + // Recalcular calidad (isColor y isHq) en funcion del cliente + [$isColor, $isHq] = PresupuestoService::getCalidad( + 'importador-rama', + null, + (in_array(strtolower($libro->tipo_impresion), ['color', 'colorhq']) ? 1 : 0), + (in_array(strtolower($libro->tipo_impresion), ['negrohq', 'colorhq']) ? 1 : 0), + intval($tirada ?? 0) + ); + $dataToImport = [ 'selectedTirada' => $tirada, @@ -246,8 +255,8 @@ class ImportadorCatalogo extends BaseResourceController '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), + 'isColor' => $isColor, + 'isHq' => $isHq, 'paginas' => $libro->paginas, 'paginasColor' => $colorPaginas, 'papelInteriorDiferente' => $papelInteriorDiferente, From 59609df471565303d7c6b7be37f5159e7d347fb5 Mon Sep 17 00:00:00 2001 From: imnavajas Date: Fri, 9 May 2025 13:54:41 +0200 Subject: [PATCH 057/127] =?UTF-8?q?A=C3=B1adidas=20modificaciones=20para?= =?UTF-8?q?=20PDF=20y=20bug=20detectado?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Importadores/ImportadorBubok.php | 24 ++-- ci4/app/Language/es/Importador.php | 2 +- .../bubok/viewImportadorBubokTool.php | 4 +- .../pages/importadores/bubok/bubok_tool.js | 113 +++++++++++------- 4 files changed, 93 insertions(+), 50 deletions(-) diff --git a/ci4/app/Controllers/Importadores/ImportadorBubok.php b/ci4/app/Controllers/Importadores/ImportadorBubok.php index 02a8e2a4..39ca1535 100644 --- a/ci4/app/Controllers/Importadores/ImportadorBubok.php +++ b/ci4/app/Controllers/Importadores/ImportadorBubok.php @@ -277,6 +277,15 @@ class ImportadorBubok extends BaseResourceController ] ]; + // Recalcular calidad (isColor y isHq) en funcion del cliente + [$isColor, $isHq] = PresupuestoService::getCalidad( + 'importador-bubok', + null, + ((trim(strtolower($interiorTipo)) === 'color') ? 1 : 0), + 0, + intval($tirada ?? 0) + ); + // Generamos el objeto a importar $dataToImport = [ 'selectedTirada' => $tirada, @@ -295,8 +304,8 @@ class ImportadorBubok extends BaseResourceController 'tipo' => '', 'tipo_presupuesto_id' => $encuadernadoId, 'clienteId' => 40, // BUBOK ID - 'isColor' => ($interiorTipo === 'color') ? 1 : 0, - 'isHq' => 0, + 'isColor' => $isColor, + 'isHq' => $isHq, 'paginas' => $paginas, 'paginasColor' => ($interiorTipo === 'color') ? $paginas : 0, 'paginasCuadernillo' => 32, @@ -317,16 +326,17 @@ class ImportadorBubok extends BaseResourceController 'sobrecubierta' => [], 'faja' => null, - 'entrega_taller' => 1, - //'direcciones' => $direcciones, las direcciones que aparecen no se añaden, ya que la recogida la hacen ellos con su empresa de mensajeria + 'direcciones' => $direcciones, 'ivaReducido' => 1, ]; - /*return $this->respond([ + return $this->respond([ 'status' => 400, - 'message' => $dataToImport - ]);*/ + 'message' => $dataToImport, + 'interiorTipo' => $interiorTipo, + 'isColor' => $isColor + ]); // 5. Guardar try { diff --git a/ci4/app/Language/es/Importador.php b/ci4/app/Language/es/Importador.php index 925076fc..5f4f0ad0 100644 --- a/ci4/app/Language/es/Importador.php +++ b/ci4/app/Language/es/Importador.php @@ -12,7 +12,7 @@ return [ 'precio_compra' => 'Precio Compra', 'importar' => 'Importar', 'subirArchivoRama' => 'Cargar Excel proporcionado por RA-MA', - 'subirArchivoBubok' => 'Cargar XML proporcionado por BUBOK', + 'subirArchivoBubok' => 'Cargar ZIP proporcionado por BUBOK', 'libro' => 'libro', 'id' => 'ID', diff --git a/ci4/app/Views/themes/vuexy/form/importador/bubok/viewImportadorBubokTool.php b/ci4/app/Views/themes/vuexy/form/importador/bubok/viewImportadorBubokTool.php index 4db87bfe..1e89f976 100644 --- a/ci4/app/Views/themes/vuexy/form/importador/bubok/viewImportadorBubokTool.php +++ b/ci4/app/Views/themes/vuexy/form/importador/bubok/viewImportadorBubokTool.php @@ -22,8 +22,8 @@
- + class="form-label"> +
- + @@ -16,6 +16,20 @@ + + + + + + + + + + + + + + diff --git a/httpdocs/assets/js/safekat/components/datatables/otDatatable.js b/httpdocs/assets/js/safekat/components/datatables/otDatatable.js index 527f15f1..47a9652e 100644 --- a/httpdocs/assets/js/safekat/components/datatables/otDatatable.js +++ b/httpdocs/assets/js/safekat/components/datatables/otDatatable.js @@ -11,19 +11,18 @@ class OrdenTrabajoDatatable { this.datatableWaiting = this.item.find("#ot-datatable-waiting") this.datatableRevisionComerical = this.item.find("#ot-datatable-revision-com") - this.columnIdIndex = 1; - + this.tableLayout = "lrtip" this.datatableColumns = [ { data: 'pdf_check', searchable: false, sortable: false, render: d => `` }, - { data: 'id', searchable: true, sortable: true }, + { data: 'id', searchable: true, sortable: true}, { data: 'pedido_id', searchable: true, sortable: true }, - { data: 'fecha_encuadernado_at',name:"pedidos.fecha_encuadernado", searchable: true, sortable: true }, - { data: 'cliente_nombre', name:"clientes.nombre", searchable: true, sortable: false }, - { data: 'presupuesto_titulo', name:"presupuestos.titulo", searchable: true, sortable: true }, - { data: 'ubicacion_nombre', name:"ubicaciones.nombre", searchable: true, sortable: true }, - { data: 'total_tirada', name:"pedidos.total_tirada",searchable: true, sortable: true, render: (d) => `${d}` }, - { data: 'tipo_presupuesto_impresion', name:"tipos_presupuestos.codigo", searchable: true, sortable: true }, + { data: 'fecha_encuadernado_at', name: "pedidos.fecha_encuadernado", searchable: true, sortable: true }, + { data: 'cliente_nombre', name: "clientes.nombre", searchable: true, sortable: false }, + { data: 'presupuesto_titulo', name: "presupuestos.titulo", searchable: true, sortable: true }, + { data: 'ubicacion_nombre', name: "ubicaciones.nombre", searchable: true, sortable: true }, + { data: 'total_tirada', name: "pedidos.total_tirada", searchable: true, sortable: true, render: (d) => `${d}` }, + { data: 'tipo_presupuesto_impresion', name: "tipos_presupuestos.codigo", searchable: true, sortable: true }, { data: 'logo', searchable: false, sortable: false, render: (d, t) => { return `
@@ -33,7 +32,7 @@ class OrdenTrabajoDatatable { } }, { - data: 'progreso',name:"ordenes_trabajo.progreso", searchable: false, sortable: true, render: (d, t) => { + data: 'progreso', name: "ordenes_trabajo.progreso", searchable: false, sortable: true, render: (d, t) => { return `
${d}%
@@ -57,7 +56,7 @@ class OrdenTrabajoDatatable { console.log(order) this.focusDatatable = this.datatableOrder[order] } - events(){ + events() { this.datatableOrder = [ this.datatableN, this.datatableP, @@ -74,12 +73,8 @@ class OrdenTrabajoDatatable { init() { this.datatable = this.datatableItem.DataTable({ processing: true, - layout: { - topStart: 'pageLength', - topEnd: 'search', - bottomStart: 'info', - bottomEnd: 'paging' - }, + dom: this.tableLayout, + orderCellsTop: true, order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, @@ -97,16 +92,17 @@ class OrdenTrabajoDatatable { $(row).css("border-right", `10px solid ${data.logo.color}`) } }); + this.datatableItem.on("change", ".ot-filter", (event) => { + console.log(this.datatable.column($(event.currentTarget).attr("name"))) + let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name")) + this.datatable.column(columnIndex).search($(event.currentTarget).val()).draw() + }) } initPendientes() { this.datatableP = this.datatablePendientesItem.DataTable({ processing: true, - layout: { - topStart: 'pageLength', - topEnd: 'search', - bottomStart: 'info', - bottomEnd: 'paging' - }, + dom: this.tableLayout, + orderCellsTop: true, order: [[this.columnIdIndex, 'desc']], columnDefs: [ { className: 'dt-center', targets: '_all' }, @@ -125,16 +121,17 @@ class OrdenTrabajoDatatable { } }); + this.datatablePendientesItem.on("change", ".ot-filter", (event) => { + console.log(this.datatableP.column($(event.currentTarget).attr("name"))) + let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name")) + this.datatableP.column(columnIndex).search($(event.currentTarget).val()).draw() + }) } initFerroPendiente() { this.datatableFP = this.datatableFerroPendienteItem.DataTable({ processing: true, - layout: { - topStart: 'pageLength', - topEnd: 'search', - bottomStart: 'info', - bottomEnd: 'paging' - }, + dom: this.tableLayout, + orderCellsTop: true, serverSide: true, pageLength: 25, order: [[this.columnIdIndex, 'desc']], @@ -152,16 +149,17 @@ class OrdenTrabajoDatatable { $(row).css("border-right", `20px solid ${data.logo.color}`) } }); + this.datatableFerroPendienteItem.on("change", ".ot-filter", (event) => { + console.log(this.datatableFP.column($(event.currentTarget).attr("name"))) + let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name")) + this.datatableFP.column(columnIndex).search($(event.currentTarget).val()).draw() + }) } initFerroOk() { this.datatableFO = this.datatableFerroOkItem.DataTable({ processing: true, - layout: { - topStart: 'pageLength', - topEnd: 'search', - bottomStart: 'info', - bottomEnd: 'paging' - }, + dom: this.tableLayout, + orderCellsTop: true, serverSide: true, order: [[this.columnIdIndex, 'desc']], columnDefs: [ @@ -179,16 +177,17 @@ class OrdenTrabajoDatatable { $(row).css("border-right", `20px solid ${data.logo.color}`) } }); + this.datatableFerroOkItem.on("change", ".ot-filter", (event) => { + console.log(this.datatableFO.column($(event.currentTarget).attr("name"))) + let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name")) + this.datatableFO.column(columnIndex).search($(event.currentTarget).val()).draw() + }) } initNews() { this.datatableN = this.datatableNews.DataTable({ processing: true, - layout: { - topStart: 'pageLength', - topEnd: 'search', - bottomStart: 'info', - bottomEnd: 'paging' - }, + dom: this.tableLayout, + orderCellsTop: true, serverSide: true, order: [[this.columnIdIndex, 'desc']], columnDefs: [ @@ -207,17 +206,17 @@ class OrdenTrabajoDatatable { } }); this.focusDatatable = this.datatableN - + this.datatableNews.on("change", ".ot-filter", (event) => { + console.log(this.datatableN.column($(event.currentTarget).attr("name"))) + let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name")) + this.datatableN.column(columnIndex).search($(event.currentTarget).val()).draw() + }) } initWaiting() { this.datatableW = this.datatableWaiting.DataTable({ processing: true, - layout: { - topStart: 'pageLength', - topEnd: 'search', - bottomStart: 'info', - bottomEnd: 'paging' - }, + dom: this.tableLayout, + orderCellsTop: true, serverSide: true, order: [[this.columnIdIndex, 'desc']], columnDefs: [ @@ -235,16 +234,17 @@ class OrdenTrabajoDatatable { $(row).css("border-right", `20px solid ${data.logo.color}`) } }); + this.datatableWaiting.on("change", ".ot-filter", (event) => { + console.log(this.datatableW.column($(event.currentTarget).attr("name"))) + let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name")) + this.datatableW.column(columnIndex).search($(event.currentTarget).val()).draw() + }) } initProd() { this.datatableProduccion = this.datatableProd.DataTable({ processing: true, - layout: { - topStart: 'pageLength', - topEnd: 'search', - bottomStart: 'info', - bottomEnd: 'paging' - }, + dom: this.tableLayout, + orderCellsTop: true, serverSide: true, order: [[this.columnIdIndex, 'desc']], columnDefs: [ @@ -262,16 +262,17 @@ class OrdenTrabajoDatatable { $(row).css("border-right", `20px solid ${data.logo.color}`) } }); + this.datatableProd.on("change", ".ot-filter", (event) => { + console.log(this.datatableProduccion.column($(event.currentTarget).attr("name"))) + let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name")) + this.datatableProduccion.column(columnIndex).search($(event.currentTarget).val()).draw() + }) } initRevisionComercial() { this.datatableRC = this.datatableRevisionComerical.DataTable({ processing: true, - layout: { - topStart: 'pageLength', - topEnd: 'search', - bottomStart: 'info', - bottomEnd: 'paging' - }, + dom: this.tableLayout, + orderCellsTop: true, serverSide: true, order: [[this.columnIdIndex, 'desc']], columnDefs: [ @@ -289,6 +290,11 @@ class OrdenTrabajoDatatable { $(row).css("border-right", `20px solid ${data.logo.color}`) } }); + this.datatableRevisionComerical.on("change", ".ot-filter", (event) => { + console.log(this.datatableRC.column($(event.currentTarget).attr("name"))) + let columnIndex = this.datatableColumns.findIndex((element) => element.data == $(event.currentTarget).attr("name")) + this.datatableRC.column(columnIndex).search($(event.currentTarget).val()).draw() + }) } getSelectIDs() { return this.focusDatatable.rows((idx, data, node) => { From bbea2229d7ca34766933494ec7c6c4667fb0af44 Mon Sep 17 00:00:00 2001 From: amazuecos Date: Sat, 10 May 2025 09:25:32 +0200 Subject: [PATCH 059/127] remove preimpresion check default when create an ot --- ci4/app/Services/PresupuestoService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci4/app/Services/PresupuestoService.php b/ci4/app/Services/PresupuestoService.php index a6a80356..877daad2 100755 --- a/ci4/app/Services/PresupuestoService.php +++ b/ci4/app/Services/PresupuestoService.php @@ -1911,7 +1911,7 @@ class PresupuestoService extends BaseService $serviceProduction->setPedido($pedido); if (!$pedido->orden_trabajo()) { - $r = $serviceProduction->createOrdenTrabajo(true); + $r = $serviceProduction->createOrdenTrabajo(); $modelPedido->set(['estado' => 'produccion'])->where('id', $pedido_id)->update(); } } From 836ace0e4291388e8016193c3560434d4217f32a Mon Sep 17 00:00:00 2001 From: amazuecos Date: Sat, 10 May 2025 09:27:40 +0200 Subject: [PATCH 060/127] add check preimpresion when imported from Bubok or Catalogo --- ci4/app/Controllers/Importadores/ImportadorBubok.php | 2 +- ci4/app/Controllers/Importadores/ImportadorCatalogo.php | 2 +- ci4/app/Services/PresupuestoService.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ci4/app/Controllers/Importadores/ImportadorBubok.php b/ci4/app/Controllers/Importadores/ImportadorBubok.php index 02a8e2a4..c8955350 100644 --- a/ci4/app/Controllers/Importadores/ImportadorBubok.php +++ b/ci4/app/Controllers/Importadores/ImportadorBubok.php @@ -361,7 +361,7 @@ class ImportadorBubok extends BaseResourceController // confirmar y crear pedido y ot $presupuestoModel->confirmarPresupuesto($response['sk_id']); - PresupuestoService::crearPedido($response['sk_id']); + PresupuestoService::crearPedido($response['sk_id'],isImported:true); if (!isset($response['sk_id'])) { diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php index ca13df60..d3797f3e 100644 --- a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php +++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php @@ -359,7 +359,7 @@ class ImportadorCatalogo extends BaseResourceController // confirmar y crear pedido y ot model('App\Models\Presupuestos\PresupuestoModel')->confirmarPresupuesto($response['data']['sk_id']); - PresupuestoService::crearPedido($response['data']['sk_id']); + PresupuestoService::crearPedido($response['data']['sk_id'],isImported:true); return $this->respond($response); diff --git a/ci4/app/Services/PresupuestoService.php b/ci4/app/Services/PresupuestoService.php index 877daad2..687dfc2a 100755 --- a/ci4/app/Services/PresupuestoService.php +++ b/ci4/app/Services/PresupuestoService.php @@ -1867,7 +1867,7 @@ class PresupuestoService extends BaseService - public static function crearPedido($presupuesto_id) + public static function crearPedido($presupuesto_id,?bool $isImported = false) { $model_pedido = model('App\Models\Pedidos\PedidoModel'); $model_pedido_linea = model('App\Models\Pedidos\PedidoLineaModel'); @@ -1911,7 +1911,7 @@ class PresupuestoService extends BaseService $serviceProduction->setPedido($pedido); if (!$pedido->orden_trabajo()) { - $r = $serviceProduction->createOrdenTrabajo(); + $r = $serviceProduction->createOrdenTrabajo($isImported); $modelPedido->set(['estado' => 'produccion'])->where('id', $pedido_id)->update(); } } From 3e6ba658cd5550c958aedb7209359c309106a649 Mon Sep 17 00:00:00 2001 From: imnavajas Date: Mon, 12 May 2025 15:16:28 +0200 Subject: [PATCH 061/127] Implementados cambios del loader --- .../catalogo/viewImportadorCatalogoTool.php | 2 +- .../importadores/catalogo/catalogo_tool.js | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php b/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php index 2b1b3ea5..0bae91e3 100644 --- a/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php +++ b/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php @@ -28,7 +28,7 @@
-
diff --git a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js index cf169fce..b8ab6d44 100644 --- a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js +++ b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js @@ -2,6 +2,8 @@ import Ajax from '../../../components/ajax.js'; document.addEventListener('DOMContentLoaded', function () { + document.getElementById('importBtn').disabled = true; + const TABLE_COLUMNS = ["input", "idlinea", "descripcion", "cnt_pedida", "precio_compra"]; let dataTable; @@ -35,6 +37,9 @@ document.addEventListener('DOMContentLoaded', function () { const file = e.target.files[0]; if (!file) return; + // Deshabilitar botón importar al comenzar nuevo procesamiento + document.getElementById('importBtn').disabled = true; + const reader = new FileReader(); reader.onload = function (e) { const data = new Uint8Array(e.target.result); @@ -51,6 +56,18 @@ document.addEventListener('DOMContentLoaded', function () { async function validateAndLoadDataTable(data) { if (data.length === 0) return; + // Mostrar loader (ajústalo según tu HTML) + Swal.fire({ + title: 'Procesando...', + text: 'Cargando datos del Excel...', + allowOutsideClick: false, + showDenyButton: false, + cancelButtonText: 'Cancelar', + didOpen: () => { + Swal.showLoading(); + } + }); + const headers = data[0].map(h => h.toString().trim()); const headerMap = {}; headers.forEach((name, idx) => { @@ -60,6 +77,7 @@ document.addEventListener('DOMContentLoaded', function () { const requiredColumns = ["idpedido", ...TABLE_COLUMNS]; const missing = requiredColumns.filter(col => !(col in headerMap)); if (missing.length > 0) { + Swal.close(); // Cierra el loader Swal.fire({ title: 'Error', text: 'Faltan las siguientes columnas: ' + missing.join(', '), @@ -127,6 +145,12 @@ document.addEventListener('DOMContentLoaded', function () { dataTable.clear().rows.add(rows).draw(); setupEventListeners(); + + Swal.close(); // Ocultar loader + + // Habilitar botón importar si hay filas válidas + const tieneFilas = rows.length > 0; + document.getElementById('importBtn').disabled = !tieneFilas; } async function validarFila(rowData) { @@ -176,7 +200,7 @@ document.addEventListener('DOMContentLoaded', function () { const skId = result.data?.sk_id ?? ''; // Actualizar campo "Notas" con el enlace - if (skUrl) { + if (skUrl) { const notasHtml = `Ver presupuesto (${skId})`; // La columna de notas es la posición 6 (índice 6) rowData[6] = notasHtml; From 6ee4b1e89ddecd07704b3f9462bd526c18584698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 12 May 2025 19:19:12 +0200 Subject: [PATCH 062/127] arreglado el tema de las facturas rectificadas/rectificativas --- ci4/app/Controllers/Facturacion/Facturas.php | 9 +++++++ .../Facturacion/FacturasLineas.php | 26 +++++-------------- .../form/facturas/_facturaCabeceraItems.php | 7 +++-- .../form/facturas/_facturaLineasItems.php | 26 ++++++++++++------- .../vuexy/form/facturas/viewFacturaForm.php | 2 +- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/ci4/app/Controllers/Facturacion/Facturas.php b/ci4/app/Controllers/Facturacion/Facturas.php index ea45c3c7..7d6cf687 100755 --- a/ci4/app/Controllers/Facturacion/Facturas.php +++ b/ci4/app/Controllers/Facturacion/Facturas.php @@ -833,9 +833,18 @@ class Facturas extends \App\Controllers\BaseResourceController if ((strpos($numero, "REC ") === 0)) { $data['estado_pago'] = 'pagada'; + } $this->model->update($factura_id, $data); + + if ((strpos($numero, "REC ") === 0)) { + + $this->model->where('numero', $factura->factura_rectificada_id)->set([ + 'factura_rectificativa_id' => $numero, + 'user_updated_id' => auth()->user()->id, + ])->update(); + } } diff --git a/ci4/app/Controllers/Facturacion/FacturasLineas.php b/ci4/app/Controllers/Facturacion/FacturasLineas.php index 0c12c403..386aa70b 100755 --- a/ci4/app/Controllers/Facturacion/FacturasLineas.php +++ b/ci4/app/Controllers/Facturacion/FacturasLineas.php @@ -92,7 +92,7 @@ class FacturasLineas extends \App\Controllers\BaseResourceController Field::inst('id'), Field::inst('base'), Field::inst('total_iva'), - Field::inst('total'), + Field::inst('total')->set(Field::SET_BOTH), Field::inst('cantidad') ->validator( 'Validate::numeric', @@ -126,19 +126,6 @@ class FacturasLineas extends \App\Controllers\BaseResourceController 'message' => lang('Facturas.validation.requerido') ) ), - Field::inst('total') - ->validator( - 'Validate::numeric', - array( - 'message' => lang('Facturas.validation.numerico') - ) - ) - ->validator( - 'Validate::notEmpty', - array( - 'message' => lang('Facturas.validation.requerido') - ) - ), Field::inst('pedido_linea_impresion_id') ->setFormatter(function ($val, $data, $opts) { return $val === '' ? null : $val; @@ -157,7 +144,7 @@ class FacturasLineas extends \App\Controllers\BaseResourceController $values['total'], $values['iva'], $values['cantidad'], - $values['old_cantidad'], + $values['old_cantidad'], $values['base'] ); $editor @@ -183,7 +170,7 @@ class FacturasLineas extends \App\Controllers\BaseResourceController $values['total'], $values['iva'], $values['cantidad'], - $values['old_cantidad'], + $values['old_cantidad'], $values['base'] ); $editor @@ -256,14 +243,13 @@ class FacturasLineas extends \App\Controllers\BaseResourceController $values['base'] = $base; $values['total_iva'] = $total_iva; $values['total'] = $total; - } - else{ + } else { // se pasa la base y el iva $total_iva = round($base_input * $iva / 100, 2); $total = round($base_input + $total_iva, 2); - + $values = []; - $values['base'] = $base_input; + $values['base'] = (float) $base_input; $values['total_iva'] = $total_iva; $values['total'] = $total; diff --git a/ci4/app/Views/themes/vuexy/form/facturas/_facturaCabeceraItems.php b/ci4/app/Views/themes/vuexy/form/facturas/_facturaCabeceraItems.php index 2abd8168..6f58ad99 100755 --- a/ci4/app/Views/themes/vuexy/form/facturas/_facturaCabeceraItems.php +++ b/ci4/app/Views/themes/vuexy/form/facturas/_facturaCabeceraItems.php @@ -96,13 +96,12 @@
-
serie_id == 7 || $facturaEntity->serie_id == 9 || $facturaEntity->factura_rectificada_id != null) ? "":"style='display:none;'" ?> class="col-md-12 col-lg-2 px-4 factura-R"> +
serie_id == 7 || $facturaEntity->serie_id == 9 || $facturaEntity->factura_rectificativa_id != null) ? "":"style='display:none;'" ?> class="col-md-12 col-lg-2 px-4 factura-R">
- estado!='borrador')? "disabled":"" ?> id="facturaR" name="factura_rectificada_id != null) ? 'factura_rectificada_id' : 'factura_rectificativa_id' ?>" tabindex="" maxLength="25" class="form-control update-cabecera factura-R" - + estado!='borrador')? "disabled":"" ?> id="facturaR" name="serie_id == 7 || $facturaEntity->serie_id == 9) ? 'factura_rectificada_id' : 'factura_rectificativa_id' ?>" tabindex="" maxLength="25" class="form-control update-cabecera factura-R" factura_rectificada_id == null && $facturaEntity->factura_rectificativa_id == null): ?> value="" diff --git a/ci4/app/Views/themes/vuexy/form/facturas/_facturaLineasItems.php b/ci4/app/Views/themes/vuexy/form/facturas/_facturaLineasItems.php index 013753d8..4898bb8b 100755 --- a/ci4/app/Views/themes/vuexy/form/facturas/_facturaLineasItems.php +++ b/ci4/app/Views/themes/vuexy/form/facturas/_facturaLineasItems.php @@ -211,7 +211,7 @@ var editor_lineas = new $.fn.dataTable.Editor( { name: "base", attr: { type: "text", - name : "total", + name : "base", class :"autonumeric" } }, { @@ -224,6 +224,10 @@ var editor_lineas = new $.fn.dataTable.Editor( { name: "id", type: "hidden" }, + { + name: "total", + type: "hidden" + } ] } ); @@ -279,7 +283,8 @@ editor_lineas.on( 'preEdit', function ( e, json, data, id ) { editor_lineas.on( 'postSubmit', function ( e, json, data, action ) { - yeniden(json.); + tableLineas.clearPipeline(); + tableLineas.draw(); }); editor_lineas.on( 'submitSuccess', function ( e, json, data, action ) { @@ -495,7 +500,7 @@ var tableLineas = $('#tableOfLineasFactura').DataTable({ $('#total-iva-sum-4').closest('tr').addClass('d-none'); } else{ - totalTotal += totalIVA_4; + //totalTotal += totalIVA_4; $('#total-iva-sum-4').closest('tr').removeClass('d-none'); } autoNumericIVA_21.set(totalIVA_21); @@ -503,17 +508,18 @@ var tableLineas = $('#tableOfLineasFactura').DataTable({ $('#total-iva-sum-21').closest('tr').addClass('d-none'); } else{ - totalTotal += totalIVA_21; + //totalTotal += totalIVA_21; $('#total-iva-sum-21').closest('tr').removeClass('d-none'); } autoNumericTotal.set(totalTotal); - var total_pagos = autoNumericTotalCobrado.getNumber(); - var pendientePago = totalTotal - total_pagos; - - if (isNaN(pendientePago)) pendientePago = 0; - - autoNumericPendientePago.set(pendientePago); + if(!(serie_id ?> == 7 || serie_id ?> == 9)){ + var total_pagos = autoNumericTotalCobrado.getNumber(); + var pendientePago = totalTotal - total_pagos; + if (isNaN(pendientePago)) pendientePago = 0; + autoNumericPendientePago.set(pendientePago); + } + $.ajax({ url: 'id) ?>', diff --git a/ci4/app/Views/themes/vuexy/form/facturas/viewFacturaForm.php b/ci4/app/Views/themes/vuexy/form/facturas/viewFacturaForm.php index 23911b81..4f95d139 100755 --- a/ci4/app/Views/themes/vuexy/form/facturas/viewFacturaForm.php +++ b/ci4/app/Views/themes/vuexy/form/facturas/viewFacturaForm.php @@ -17,7 +17,7 @@ getErrors()) ? $validation->listErrors("bootstrap_style") : "" ?> - estado =='borrador') : ?> + estado =='borrador' && !($facturaEntity->serie_id == 7 || $facturaEntity->serie_id == 9)) : ?> From 565ef7f170cc11f0901d67b8ff324e1f11630861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 12 May 2025 21:32:59 +0200 Subject: [PATCH 063/127] arreglado --- ci4/app/Models/Facturas/FacturaModel.php | 29 ++++++++++++++++-------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/ci4/app/Models/Facturas/FacturaModel.php b/ci4/app/Models/Facturas/FacturaModel.php index 7c2c8142..1cfbddb0 100755 --- a/ci4/app/Models/Facturas/FacturaModel.php +++ b/ci4/app/Models/Facturas/FacturaModel.php @@ -27,9 +27,9 @@ class FacturaModel extends \App\Models\BaseModel ]; const SORTABLE_PEDIDOS = [ - 1 => "t1.numero", - 2 => "t2.nombre", - 3 => "t4.cantidad", + 1 => "t1.id", + 2 => "t1.numero", + 3 => "t4.ejemplares", 4 => "t2.nombre", 5 => "t1.estado", 6 => "t1.fecha_factura_at", @@ -129,7 +129,7 @@ class FacturaModel extends \App\Models\BaseModel $builder->join("clientes t2", "t2.id = t1.cliente_id", "left"); $builder->join("facturas_pagos t3", "t3.factura_id = t1.id", "left"); $builder->join("formas_pago t4", "t3.forma_pago_id = t4.id", "left"); - + $builder->where("t1.deleted_at", null); if (auth()->user()->inGroup("cliente-admin") || auth()->user()->inGroup("cliente-editor")) { @@ -140,7 +140,7 @@ class FacturaModel extends \App\Models\BaseModel $builder->where("t1.cliente_id", $cliente_id); } - $builder->groupBy("t1.id"); + $builder->groupBy("t1.id"); //$query = $builder->getCompiledSelect(); return $builder; } @@ -166,9 +166,10 @@ class FacturaModel extends \App\Models\BaseModel return !empty($result); } - public function getSumatoriosFacturacionCliente($cliente_id = -1){ + public function getSumatoriosFacturacionCliente($cliente_id = -1) + { - if($cliente_id == -1){ + if ($cliente_id == -1) { return [ 'total_facturacion' => 0, 'total_pendiente' => 0 @@ -183,7 +184,7 @@ class FacturaModel extends \App\Models\BaseModel ->where('f.estado', 'validada') ->get() ->getResultObject(); - $result['total_facturacion'] = + $result['total_facturacion'] = round(floatval(($data && $data[0]->total != null) ? $data[0]->total : 0), 2); $data = $this->db->table('facturas f') @@ -253,7 +254,17 @@ class FacturaModel extends \App\Models\BaseModel $builder->join("pedidos t6", "t5.pedido_id = t6.id", "left"); $builder->where("t1.deleted_at IS NULL"); - $builder->where("t6.id", $pedido_id); + $builder->groupStart() + ->where("t6.id", $pedido_id) + ->orWhere("t1.factura_rectificada_id IN ( + SELECT f.numero + FROM facturas f + JOIN facturas_pedidos_lineas fpl ON f.id = fpl.factura_id + JOIN pedidos_linea pl ON fpl.pedido_linea_id = pl.id + JOIN pedidos p ON pl.pedido_id = p.id + WHERE p.id = {$pedido_id} + )") + ->groupEnd(); $builder->groupBy("t1.id"); // Agrupa por id de la factura From 6ba2694733acc8af73bf699551b1d82ec10458bf Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Mon, 12 May 2025 22:36:07 +0200 Subject: [PATCH 064/127] Subido script para comprobar identidades --- ci4/app/Config/Routes/ScriptsRoutes.php | 13 ++++ .../Controllers/Scripts/UsersIntegrity.php | 76 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 ci4/app/Config/Routes/ScriptsRoutes.php create mode 100644 ci4/app/Controllers/Scripts/UsersIntegrity.php diff --git a/ci4/app/Config/Routes/ScriptsRoutes.php b/ci4/app/Config/Routes/ScriptsRoutes.php new file mode 100644 index 00000000..f7e994c9 --- /dev/null +++ b/ci4/app/Config/Routes/ScriptsRoutes.php @@ -0,0 +1,13 @@ +group('scripts', ['namespace' => 'App\Controllers\Scripts'], function ($routes) { + + $routes->get('completar-identidades', 'UsersIntegrity::completarIdentidades'); + + +}); \ No newline at end of file diff --git a/ci4/app/Controllers/Scripts/UsersIntegrity.php b/ci4/app/Controllers/Scripts/UsersIntegrity.php new file mode 100644 index 00000000..5b7aa986 --- /dev/null +++ b/ci4/app/Controllers/Scripts/UsersIntegrity.php @@ -0,0 +1,76 @@ +where('deleted_at', null) + //->like('username', '@safekat.com') + ->findAll(); + + $resultados = []; + + foreach ($usuarios as $usuario) { + $email = $usuario->username . "@safekat.com"; + + // 1. Verificar si el usuario ya tiene identidad tipo email_password + $tieneIdentidad = array_filter( + $usuario->getIdentities(), + fn($identity) => $identity->type === 'email_password' + ); + + if (!empty($tieneIdentidad)) { + $resultados[] = "✅ Ya tiene identidad: {$email}"; + continue; + } + + // 2. Verificar si ya existe una identidad globalmente con ese email + $db = db_connect(); + + $builder = $db->table('auth_identities'); + + $existeGlobal = $builder + ->where('type', 'email_password') + ->where('secret', $email) + ->get() + ->getFirstRow(); + + if ($existeGlobal) { + $resultados[] = "⚠️ Email ya registrado en otra identidad: {$email}"; + continue; + } + + // 3. Crear y guardar identidad + try { + $identity = $usuario->createEmailIdentity([ + 'email' => $email, + 'password' => 'Temporal123!', // reemplazar por valor real si lo tenés + ]); + + //$userModel->saveEmailIdentity($identity); + + $resultados[] = "➕ Identidad creada: {$email}"; + } catch (\Throwable $e) { + $resultados[] = "❌ Error con {$email}: " . $e->getMessage(); + } + } + + return $this->response->setJSON([ + 'status' => 'completado', + 'procesados' => count($usuarios), + 'resultados' => $resultados, + ]); + } +} From fa77952ea66919376760675db8b4c2cf9cd5a9cf Mon Sep 17 00:00:00 2001 From: imnavajas Date: Tue, 13 May 2025 13:28:54 +0200 Subject: [PATCH 065/127] Corregidos bugs y homegeneizado --- ci4/app/Config/Routes/ImportadoresRoutes.php | 1 + ci4/app/Config/Routes/ScriptsRoutes.php | 2 +- .../Importadores/ImportadorBubok.php | 80 +++++- .../pages/importadores/bubok/bubok_tool.js | 230 +++++++++++++----- 4 files changed, 242 insertions(+), 71 deletions(-) diff --git a/ci4/app/Config/Routes/ImportadoresRoutes.php b/ci4/app/Config/Routes/ImportadoresRoutes.php index 2706aa8c..f3e20ae5 100644 --- a/ci4/app/Config/Routes/ImportadoresRoutes.php +++ b/ci4/app/Config/Routes/ImportadoresRoutes.php @@ -32,6 +32,7 @@ $routes->group('importador', ['namespace' => 'App\Controllers\Importadores'], fu /**====================== * AJAX *========================**/ + $routes->post('validar-fila', 'ImportadorBubok::validarFila'); $routes->post('importar-fila', 'ImportadorBubok::importarFila'); }); diff --git a/ci4/app/Config/Routes/ScriptsRoutes.php b/ci4/app/Config/Routes/ScriptsRoutes.php index f7e994c9..d3744033 100644 --- a/ci4/app/Config/Routes/ScriptsRoutes.php +++ b/ci4/app/Config/Routes/ScriptsRoutes.php @@ -7,7 +7,7 @@ use CodeIgniter\Router\RouteCollection; /* Rutas para tarifas */ $routes->group('scripts', ['namespace' => 'App\Controllers\Scripts'], function ($routes) { - $routes->get('completar-identidades', 'UsersIntegrity::completarIdentidades'); + //$routes->get('completar-identidades', 'UsersIntegrity::completarIdentidades'); }); \ No newline at end of file diff --git a/ci4/app/Controllers/Importadores/ImportadorBubok.php b/ci4/app/Controllers/Importadores/ImportadorBubok.php index 33fcc4d5..27641c64 100644 --- a/ci4/app/Controllers/Importadores/ImportadorBubok.php +++ b/ci4/app/Controllers/Importadores/ImportadorBubok.php @@ -3,6 +3,7 @@ namespace App\Controllers\Importadores; use App\Controllers\BaseResourceController; use App\Controllers\Presupuestos\Presupuestocliente; +use App\Models\Presupuestos\PresupuestoModel; use App\Services\PresupuestoService; class ImportadorBubok extends BaseResourceController @@ -50,6 +51,73 @@ class ImportadorBubok extends BaseResourceController return view(static::$viewPath . 'viewImportadorBubokTool', $viewData); } + public function validarFila() + { + $json = $this->request->getJSON(); + + if (!$json || empty($json->producto) || empty($json->pedido)) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'Datos incompletos' + ]); + } + + $producto = $json->producto; + $pedido = $json->pedido; + + // Validar existencia de ID de producto + if (empty($producto->id)) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'ID de producto no proporcionado' + ]); + } + + $refCliente = $pedido->orderNumber . '-' . $producto->id; + + // Validar formato Ref. Cliente + if (strpos($refCliente, '-') === false || strlen($refCliente) < 5) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'Ref. cliente inválido' + ]); + } + + // 1. Verificar si ya fue importado + $presupuestoModel = new PresupuestoModel(); + $yaExiste = $presupuestoModel->where('referencia_cliente', $refCliente)->first(); + + if ($yaExiste) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'Referencia ya importada' + ]); + } + + // 2. Validación básica del producto (puedes expandir con más reglas si lo necesitas) + $errores = []; + + if (empty($producto->title)) + $errores[] = 'Falta título'; + if (empty($producto->body->pages)) + $errores[] = 'Faltan páginas'; + if (empty($producto->amount)) + $errores[] = 'Falta tirada'; + + if (!empty($errores)) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => implode(', ', $errores) + ]); + } + + // 3. Producto considerado apto + return $this->response->setJSON([ + 'apto' => true + ]); + } + + public function importarFila() { @@ -83,7 +151,7 @@ class ImportadorBubok extends BaseResourceController 'message' => 'Número de orden o ID del producto no reconocidos.' ]); } - $refCliente = "$orderNumber - $productId"; + $refCliente = "$orderNumber-$productId"; // Titulo $titulo = $producto->title ?? null; @@ -331,12 +399,12 @@ class ImportadorBubok extends BaseResourceController 'ivaReducido' => 1, ]; - return $this->respond([ + /*return $this->respond([ 'status' => 400, 'message' => $dataToImport, 'interiorTipo' => $interiorTipo, 'isColor' => $isColor - ]); + ]);*/ // 5. Guardar try { @@ -368,11 +436,11 @@ class ImportadorBubok extends BaseResourceController ]; } } - + // confirmar y crear pedido y ot $presupuestoModel->confirmarPresupuesto($response['sk_id']); - PresupuestoService::crearPedido($response['sk_id'],isImported:true); - + PresupuestoService::crearPedido($response['sk_id'], isImported: true); + if (!isset($response['sk_id'])) { return $this->respond([ diff --git a/httpdocs/assets/js/safekat/pages/importadores/bubok/bubok_tool.js b/httpdocs/assets/js/safekat/pages/importadores/bubok/bubok_tool.js index 76325766..b86902b1 100644 --- a/httpdocs/assets/js/safekat/pages/importadores/bubok/bubok_tool.js +++ b/httpdocs/assets/js/safekat/pages/importadores/bubok/bubok_tool.js @@ -1,8 +1,11 @@ document.addEventListener('DOMContentLoaded', function () { + let dataTable; let productosOriginales = []; let datosComunesPedido = {}; + document.getElementById('importBtn').disabled = true; + document.getElementById('xmlFile').addEventListener('change', function (e) { const file = e.target.files[0]; if (!file || !file.name.endsWith('.zip')) { @@ -10,10 +13,19 @@ document.addEventListener('DOMContentLoaded', function () { return; } + document.getElementById('importBtn').disabled = true; + const reader = new FileReader(); reader.onload = async function (event) { try { const zip = await JSZip.loadAsync(event.target.result); + + // Reset tabla y memoria de productos + if (dataTable) { + dataTable.clear().draw(); + } + productosOriginales = []; + const xmlFiles = Object.values(zip.files).filter(f => f.name.endsWith('.xml') && !f.name.startsWith('__MACOSX/') ); @@ -23,11 +35,20 @@ document.addEventListener('DOMContentLoaded', function () { return; } + Swal.fire({ + title: 'Procesando...', + text: 'Cargando XMLs...', + allowOutsideClick: false, + showDenyButton: false, + didOpen: () => Swal.showLoading() + }); + for (const file of xmlFiles) { const content = await file.async('text'); - parseXmlAndLoadTable(content); + await parseXmlAndLoadTable(content); } + Swal.close(); Swal.fire('Éxito', `${xmlFiles.length} archivos XML cargados.`, 'success'); } catch (err) { console.error(err); @@ -38,8 +59,8 @@ document.addEventListener('DOMContentLoaded', function () { reader.readAsArrayBuffer(file); }); - function parseXmlAndLoadTable(xmlText) { - let parser = new DOMParser(); + async function parseXmlAndLoadTable(xmlText) { + const parser = new DOMParser(); let xmlDoc; try { @@ -50,7 +71,7 @@ document.addEventListener('DOMContentLoaded', function () { return; } - datosComunesPedido = { + const pedidoActual = { orderNumber: xmlDoc.querySelector('orderNumber')?.textContent ?? '', shipping: { address: xmlDoc.querySelector('shippingData > address')?.textContent ?? '', @@ -65,13 +86,19 @@ document.addEventListener('DOMContentLoaded', function () { const products = Array.from(xmlDoc.getElementsByTagName('product')); const offset = productosOriginales.length; + const rows = []; - products.forEach((prod, idx) => { - productosOriginales.push({ index: offset + idx, data: prod }); - }); + for (let i = 0; i < products.length; i++) { + const product = products[i]; + const globalIndex = offset + i; + + // Asociar producto con su pedido + productosOriginales.push({ + index: globalIndex, + data: product, + pedido: { ...pedidoActual } + }); - const rows = products.map((product, index) => { - const globalIndex = offset + index; const id = product.querySelector('id')?.textContent ?? ''; const title = product.querySelector('title')?.textContent ?? ''; const pages = product.querySelector('body > pages')?.textContent ?? ''; @@ -97,40 +124,65 @@ document.addEventListener('DOMContentLoaded', function () { } }); - return [ - ``, - `${datosComunesPedido.orderNumber} - ${id}`, - title, - tamano, - pages, - tirada, - interior, - '', - ` - ` - ]; - }); + // Obtener referencia del pedido + const refCliente = `${pedidoActual.orderNumber}-${id}`; + + // Validar fila con su propio pedido + const result = await validarProductoXml(product, pedidoActual); + + let checkboxHtml = ''; + let notaHtml = ''; + let actionBtnsHtml = ''; + + if (result.apto) { + checkboxHtml = ``; + notaHtml = ''; + actionBtnsHtml = ` +
+ + +
+ `; + } else { + checkboxHtml = ``; + notaHtml = `${result.reason}`; + actionBtnsHtml = ` +
+ No Apto + +
+ `; + } + + rows.push([checkboxHtml, refCliente, title, tamano, pages, tirada, interior, notaHtml, actionBtnsHtml]); + } if (!$.fn.DataTable.isDataTable('#xmlTable')) { - const headerHtml = ` -
- - - - - - - - - - - - - - - - `; - $('#xmlTable').html(headerHtml); + $('#xmlTable').html(` + + + + + + + + + + + + + + + + + + `); } if (!dataTable) { @@ -141,6 +193,8 @@ document.addEventListener('DOMContentLoaded', function () { responsive: true, scrollX: true, dom: 'lfrtip', + pageLength: 25, + lengthMenu: [5, 10, 25, 50, 100, 250, 500], language: { url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" }, @@ -163,8 +217,36 @@ document.addEventListener('DOMContentLoaded', function () { rows.forEach(row => dataTable.row.add(row)); dataTable.draw(false); } + + if (rows.length > 0) { + document.getElementById('importBtn').disabled = false; + } } + + async function validarProductoXml(productoXml, pedido) { + try { + const response = await fetch('/importador/bubok/validar-fila', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-TOKEN': '' + }, + body: JSON.stringify({ + producto: xmlToJson(productoXml), + pedido: pedido + }) + }); + + return await response.json(); + } catch (error) { + console.error('Error validando producto:', error); + return { apto: false, reason: 'Error conexión' }; + } + } + + + function setupEventListeners() { $('#xmlTable tbody').off('click', '.deleteRow').on('click', '.deleteRow', function () { dataTable.row($(this).parents('tr')).remove().draw(); @@ -173,9 +255,12 @@ document.addEventListener('DOMContentLoaded', function () { $('#xmlTable tbody').off('click', '.importRow').on('click', '.importRow', async function () { const $row = $(this).closest('tr'); const rowIndex = dataTable.row($row).index(); - const xmlProduct = productosOriginales.find(p => p.index === rowIndex)?.data; + const productoObj = productosOriginales.find(p => p.index === rowIndex); - if (!xmlProduct) return; + if (!productoObj) return; + + const xmlProduct = productoObj.data; + const pedido = productoObj.pedido; try { const response = await fetch('/importador/bubok/importar-fila', { @@ -186,32 +271,46 @@ document.addEventListener('DOMContentLoaded', function () { }, body: JSON.stringify({ producto: xmlToJson(xmlProduct), - pedido: datosComunesPedido + pedido: pedido }) }); const result = await response.json(); - const rowData = dataTable.row($row).data(); + if (response.ok && result.status === 200) { const skUrl = result.data?.sk_url?.replace('presupuestocliente', 'presupuestoadmin') ?? null; - const htmlLink = skUrl - ? `Ver presupuesto` - : 'Importado'; - rowData[7] = htmlLink; + const skId = result.data?.sk_id ?? ''; + + rowData[7] = skUrl + ? `Ver presupuesto (${skId})` + : `Importado (${skId})`; + dataTable.row($row).data(rowData).draw(false); + let html = skUrl + ? `La fila se importó exitosamente.

Ver presupuesto (${skId})` + : `La fila se importó exitosamente. (${skId})`; + + let icon = 'success'; + + if (result.price_warning) { + html = skUrl + ? `La fila se importó con éxito, pero el precio fue ajustado por debajo de costes.

Ver presupuesto (${skId})` + : `La fila se importó con advertencia de coste. (${skId})`; + icon = 'warning'; + } + Swal.fire({ title: 'Importado correctamente', - html: skUrl - ? `Se importó correctamente.
Ver presupuesto` - : 'Importación realizada.', - icon: 'success', + html: html, + icon: icon, confirmButtonText: 'Aceptar', customClass: { confirmButton: 'btn btn-success' } }); + } else { - rowData[7] = `${result.message ?? 'Error inesperado'}`; + rowData[7] = `${result.message ?? 'Error desconocido'}`; dataTable.row($row).data(rowData).draw(false); Swal.fire({ @@ -222,15 +321,14 @@ document.addEventListener('DOMContentLoaded', function () { customClass: { confirmButton: 'btn btn-danger' } }); } - - dataTable.row($row).data(rowData).draw(false); - - } catch (err) { - console.error(err); + } catch (error) { + console.error('Importación fallida:', error); Swal.fire('Error', 'Error de comunicación con el servidor.', 'error'); } }); + + $('#selectAll').off('change').on('change', function () { const checked = $(this).is(':checked'); $('#xmlTable tbody input.select-row:enabled').prop('checked', checked); @@ -329,8 +427,11 @@ document.addEventListener('DOMContentLoaded', function () { if (!result.isConfirmed) return; for (const i of filasSeleccionadas) { - const productXml = productosOriginales.find(p => p.index === i)?.data; - if (!productXml) continue; + const productoObj = productosOriginales.find(p => p.index === i); + if (!productoObj) continue; + + const productXml = productoObj.data; + const pedido = productoObj.pedido; try { const response = await fetch('/importador/bubok/importar-fila', { @@ -341,7 +442,7 @@ document.addEventListener('DOMContentLoaded', function () { }, body: JSON.stringify({ producto: xmlToJson(productXml), - pedido: datosComunesPedido + pedido: pedido }) }); @@ -351,9 +452,10 @@ document.addEventListener('DOMContentLoaded', function () { if (response.ok && result.status === 200) { const skUrl = result.data?.sk_url?.replace('presupuestocliente', 'presupuestoadmin') ?? null; + const skId = result.data?.sk_id ?? ''; rowData[7] = skUrl - ? `Ver presupuesto` - : 'Importado'; + ? `Ver presupuesto (${skId})` + : `Importado (${skId})`; } else { rowData[7] = `${result.message ?? 'Error desconocido'}`; } From 199e5f2018c790d6cba98c6a5460e0eadb039020 Mon Sep 17 00:00:00 2001 From: imnavajas Date: Tue, 13 May 2025 15:40:04 +0200 Subject: [PATCH 066/127] =?UTF-8?q?A=C3=B1adidos=20enlaces=20a=20facturas?= =?UTF-8?q?=20rectificativas/rectificadas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci4/app/Entities/Facturas/FacturaEntity.php | 10 ++++++++++ ci4/app/Language/es/Facturas.php | 4 ++-- .../vuexy/form/facturas/_facturaCabeceraItems.php | 11 ++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ci4/app/Entities/Facturas/FacturaEntity.php b/ci4/app/Entities/Facturas/FacturaEntity.php index 99f923b5..ce2ab573 100755 --- a/ci4/app/Entities/Facturas/FacturaEntity.php +++ b/ci4/app/Entities/Facturas/FacturaEntity.php @@ -48,4 +48,14 @@ class FacturaEntity extends \CodeIgniter\Entity\Entity 'creditoAsegurado' => 'float', ]; + public function getIdFromNumero(string $numero): ?int + { + $facturaModel = model('\App\Models\Facturas\FacturaModel'); + $factura = $facturaModel->where('numero', $numero)->first(); + + return $factura?->id; + } + + + } \ No newline at end of file diff --git a/ci4/app/Language/es/Facturas.php b/ci4/app/Language/es/Facturas.php index fd058b51..1765a9da 100755 --- a/ci4/app/Language/es/Facturas.php +++ b/ci4/app/Language/es/Facturas.php @@ -21,8 +21,8 @@ return [ 'dias' => 'Días', 'serieFacturacion' => 'Serie facturación', 'creditoAsegurado' => 'Crédito asegurado', - 'facturaRectificada' => 'Factura rectificada', - 'facturaRectificativa' => 'Factura rectificativa', + 'facturaRectificada' => 'Fact. rectificada', + 'facturaRectificativa' => 'Fact. rectificativa', 'razonSocial' => 'Razón Social', 'cif' => 'CIF', 'direccion' => 'Dirección', diff --git a/ci4/app/Views/themes/vuexy/form/facturas/_facturaCabeceraItems.php b/ci4/app/Views/themes/vuexy/form/facturas/_facturaCabeceraItems.php index 6f58ad99..53c9141c 100755 --- a/ci4/app/Views/themes/vuexy/form/facturas/_facturaCabeceraItems.php +++ b/ci4/app/Views/themes/vuexy/form/facturas/_facturaCabeceraItems.php @@ -99,7 +99,16 @@
serie_id == 7 || $facturaEntity->serie_id == 9 || $facturaEntity->factura_rectificativa_id != null) ? "":"style='display:none;'" ?> class="col-md-12 col-lg-2 px-4 factura-R">
estado!='borrador')? "disabled":"" ?> id="facturaR" name="serie_id == 7 || $facturaEntity->serie_id == 9) ? 'factura_rectificada_id' : 'factura_rectificativa_id' ?>" tabindex="" maxLength="25" class="form-control update-cabecera factura-R" factura_rectificada_id == null && $facturaEntity->factura_rectificativa_id == null): ?> From bc7929f44ba70f7429df07ba290b6abcd8f2f405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 13 May 2025 20:18:44 +0200 Subject: [PATCH 067/127] terminado --- ci4/app/Config/Routes.php | 1 + ci4/app/Controllers/Facturacion/Facturas.php | 12 +- .../Controllers/Facturacion/FacturasPagos.php | 32 +++++ ci4/app/Language/es/Facturas.php | 4 + .../form/facturas/_facturaLineasItems.php | 41 +++--- .../form/facturas/_pagosFacturasItems.php | 33 +++-- .../facturas/_rectificadaFacturasItems.php | 41 +++++- .../vuexy/form/facturas/viewFacturaForm.php | 4 + .../js/safekat/pages/facturas/facturasEdit.js | 132 ++++++++++++++++++ 9 files changed, 257 insertions(+), 43 deletions(-) create mode 100644 httpdocs/assets/js/safekat/pages/facturas/facturasEdit.js diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index dfdda020..03ad8f11 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -552,6 +552,7 @@ $routes->group('facturas', ['namespace' => 'App\Controllers\Facturacion'], funct $routes->post('updateTotales/(:any)', 'Facturas::updateTotales/$1', ['as' => 'updateFacturaTotales']); $routes->post('updateCabecera/(:any)', 'Facturas::updateCabecera/$1', ['as' => 'updateCabecera']); $routes->post('datatablePagos/(:any)', 'FacturasPagos::datatable/$1', ['as' => 'dataTableOfPagosFacturas']); + $routes->post('conformarFactura', 'FacturasPagos::addPagoRectificativa'); $routes->post('editorPagos', 'FacturasPagos::datatable_editor', ['as' => 'editorOfPagosFacturas']); $routes->post('deleteFacturaLineaPago', 'Facturas::deleteLineaPago', ['as' => 'deleteLineaPago']); $routes->post('datatablePedidos', 'Facturas::datatablePedidos', ['as' => 'dataTableOfFacturasPedido']); diff --git a/ci4/app/Controllers/Facturacion/Facturas.php b/ci4/app/Controllers/Facturacion/Facturas.php index 7d6cf687..6f19d4b4 100755 --- a/ci4/app/Controllers/Facturacion/Facturas.php +++ b/ci4/app/Controllers/Facturacion/Facturas.php @@ -234,6 +234,13 @@ class Facturas extends \App\Controllers\BaseResourceController $factura->showDeleteButton = model('App\Models\Facturas\FacturaPagoModel') ->where('factura_id', $factura->id)->countAllResults() == 0; + if($factura->numero != null && $factura->numero != '' && strpos($factura->numero, "REC ") === 0) { + $modelPagos = model('App\Models\Facturas\FacturaPagoModel'); + if($modelPagos->where('factura_id', $factura->id)->countAllResults() > 0) { + $factura->facturaRectificativaPagada = 1; + } + } + $this->viewData['facturaEntity'] = $factura; $this->viewData['boxTitle'] = lang('Basic.global.edit2') . ' ' . lang('Facturas.factura') . ' ' . lang('Basic.global.edit3'); @@ -831,11 +838,6 @@ class Facturas extends \App\Controllers\BaseResourceController 'user_updated_id' => auth()->user()->id, ]; - if ((strpos($numero, "REC ") === 0)) { - $data['estado_pago'] = 'pagada'; - - } - $this->model->update($factura_id, $data); if ((strpos($numero, "REC ") === 0)) { diff --git a/ci4/app/Controllers/Facturacion/FacturasPagos.php b/ci4/app/Controllers/Facturacion/FacturasPagos.php index 42a46009..c358f131 100755 --- a/ci4/app/Controllers/Facturacion/FacturasPagos.php +++ b/ci4/app/Controllers/Facturacion/FacturasPagos.php @@ -136,4 +136,36 @@ class FacturasPagos extends \App\Controllers\BaseResourceController } } + public function addPagoRectificativa() + { + if ($this->request->isAJAX()) { + $data['factura_id'] = $this->request->getPost('factura_id'); + $data['fecha_vencimiento_at'] = $this->request->getPost('fecha'); + $data['total'] = $this->request->getPost('total'); + $data['user_updated_id'] = auth()->user()->id; + $data['forma_pago_id'] = 6; // compensada + + if($data['fecha_vencimiento_at'] != null && $data['fecha_vencimiento_at'] != '') { + $data['fecha_vencimiento_at'] = date('Y-m-d H:i:s', strtotime($data['fecha_vencimiento_at'])); + } + + $model = new FacturaPagoModel(); + $model->insert($data); + + $modelFactura = model('App\Models\Facturas\FacturaModel'); + $modelFactura->update($data['factura_id'], [ + 'estado_pago' => 'pagada', + 'updated_at' => date('Y-m-d H:i:s'), + 'user_updated_id' => auth()->user()->id, + ]); + + return $this->response->setJSON([ + 'status' => true, + 'message' => lang('Facturas.facturaConformada'), + ]); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + } \ No newline at end of file diff --git a/ci4/app/Language/es/Facturas.php b/ci4/app/Language/es/Facturas.php index 1765a9da..b23ee416 100755 --- a/ci4/app/Language/es/Facturas.php +++ b/ci4/app/Language/es/Facturas.php @@ -77,6 +77,10 @@ return [ "acumuladoFacturacion" => "Acumulado Facturación", "totalPendientePago" => "Pendiente de pago", + + "textoConformarFactura" => "La factura rectificativa se conformará y pasará a estar pagada.", + "conformarFactura" => "Conformar factura", + "facturaConformada" => "Factura conformada correctamente", 'errors' => [ 'requiredFields' => 'Los campos marcados con * son obligatorios', diff --git a/ci4/app/Views/themes/vuexy/form/facturas/_facturaLineasItems.php b/ci4/app/Views/themes/vuexy/form/facturas/_facturaLineasItems.php index 4898bb8b..8f176216 100755 --- a/ci4/app/Views/themes/vuexy/form/facturas/_facturaLineasItems.php +++ b/ci4/app/Views/themes/vuexy/form/facturas/_facturaLineasItems.php @@ -518,28 +518,27 @@ var tableLineas = $('#tableOfLineasFactura').DataTable({ var pendientePago = totalTotal - total_pagos; if (isNaN(pendientePago)) pendientePago = 0; autoNumericPendientePago.set(pendientePago); + + $.ajax({ + url: 'id) ?>', + method: 'POST', + data: { + base: totalSubtotal, + total: totalTotal, + total_pagos: total_pagos, + pendiente: pendientePago, + : v + } + }).done(function (data) { + if (data.estado_pago === 'pagada') { + $('#estado_pago_text').text('').css('color', 'green'); + } else { + $('#estado_pago_text').text('').css('color', 'red'); + } + }).fail(function (jqXHR) { + popErrorAlert(jqXHR.responseJSON.messages.error); + }); } - - - $.ajax({ - url: 'id) ?>', - method: 'POST', - data: { - base: totalSubtotal, - total: totalTotal, - total_pagos: total_pagos, - pendiente: pendientePago, - : v - } - }).done(function (data) { - if (data.estado_pago === 'pagada') { - $('#estado_pago_text').text('').css('color', 'green'); - } else { - $('#estado_pago_text').text('').css('color', 'red'); - } - }).fail(function (jqXHR) { - popErrorAlert(jqXHR.responseJSON.messages.error); - }); } }); diff --git a/ci4/app/Views/themes/vuexy/form/facturas/_pagosFacturasItems.php b/ci4/app/Views/themes/vuexy/form/facturas/_pagosFacturasItems.php index dd555edf..68a92e6b 100755 --- a/ci4/app/Views/themes/vuexy/form/facturas/_pagosFacturasItems.php +++ b/ci4/app/Views/themes/vuexy/form/facturas/_pagosFacturasItems.php @@ -398,18 +398,31 @@ function updateFooterLineas(table){ pendiente: pendientePago } }).done((data, textStatus, jqXHR) => { - if(autoNumericPendientePago.getNumber() == 0){ - $('#addPagoRow').hide(); - } else { - $('#addPagoRow').show(); - } - if(data.estado_pago == 'pagada'){ - $('#estado_pago_text').text(''); - $('#estado_pago_text').css('color', 'green'); + if($('#numero').val().startsWith("REC")){ + + if($("#vencimiento-rectificativa").length > 0){ + $('#estado_pago_text').text(''); + $('#estado_pago_text').css('color', 'red'); + } + else{ + $('#estado_pago_text').text(''); + $('#estado_pago_text').css('color', 'green'); + } } else{ - $('#estado_pago_text').text(''); - $('#estado_pago_text').css('color', 'red'); + if(autoNumericPendientePago.getNumber() == 0){ + $('#addPagoRow').hide(); + } else { + $('#addPagoRow').show(); + } + if(data.estado_pago == 'pagada'){ + $('#estado_pago_text').text(''); + $('#estado_pago_text').css('color', 'green'); + } + else{ + $('#estado_pago_text').text(''); + $('#estado_pago_text').css('color', 'red'); + } } }).fail((jqXHR, textStatus, errorThrown) => { popErrorAlert(jqXHR.responseJSON.messages.error) diff --git a/ci4/app/Views/themes/vuexy/form/facturas/_rectificadaFacturasItems.php b/ci4/app/Views/themes/vuexy/form/facturas/_rectificadaFacturasItems.php index 1b0f5d4b..b96063ca 100755 --- a/ci4/app/Views/themes/vuexy/form/facturas/_rectificadaFacturasItems.php +++ b/ci4/app/Views/themes/vuexy/form/facturas/_rectificadaFacturasItems.php @@ -1,14 +1,41 @@

-

-
+
- -

+ + facturaRectificativaPagada)): ?> +

+ +
+
+ +
+ + +
+
+
+ +
+ +
+
+
+
@@ -16,7 +43,7 @@
-section('additionalInlineJs') ?> +section('additionalInlineJs') ?> -endSection() ?> \ No newline at end of file +endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/facturas/viewFacturaForm.php b/ci4/app/Views/themes/vuexy/form/facturas/viewFacturaForm.php index 4f95d139..03fea05c 100755 --- a/ci4/app/Views/themes/vuexy/form/facturas/viewFacturaForm.php +++ b/ci4/app/Views/themes/vuexy/form/facturas/viewFacturaForm.php @@ -139,6 +139,8 @@ function validatedConfirmed(){ + "> + endSection() ?> section('additionalExternalJs') ?> @@ -154,7 +156,9 @@ function validatedConfirmed(){ + + endSection() ?> diff --git a/httpdocs/assets/js/safekat/pages/facturas/facturasEdit.js b/httpdocs/assets/js/safekat/pages/facturas/facturasEdit.js new file mode 100644 index 00000000..97f32363 --- /dev/null +++ b/httpdocs/assets/js/safekat/pages/facturas/facturasEdit.js @@ -0,0 +1,132 @@ +import DatePicker from "../../components/datepicker.js"; + +$(() =>{ + + const fechaVencimientoRectificativa = $("#vencimiento-rectificativa"); + let fechaPagoRectificativa = null; + if(fechaVencimientoRectificativa.length > 0) { + + const option = { + altInput: true, + altFormat: "d/m/Y", + dateFormat: "Y-m-d", + allowInput: false, + } + fechaPagoRectificativa = new DatePicker(fechaVencimientoRectificativa, option); + + $('#clearRectDate').on('click', function() { + fechaPagoRectificativa.itemDate.clear(); + }) + + $('#conformarFactura').on('click', function() { + + Swal.fire({ + title: 'Atención!', + text: 'La accion de conformar la factura no se puede deshacer. ¿Desea continuar?.', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Sí', + cancelButtonText: 'Cancelar', + customClass: { + confirmButton: 'btn btn-danger me-1', + cancelButton: 'btn btn-secondary' + }, + buttonsStyling: false + }).then((result) => { + if (result.isConfirmed) { + + if(fechaVencimientoRectificativa.val() == null || fechaVencimientoRectificativa.val() == "") { + Swal.fire({ + title: 'Error', + text: "La fecha de vencimiento no puede estar vacía.", + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + return; + } + + const total = new AutoNumeric('#total-sum', { + decimalPlaces: 2, + digitGroupSeparator: '.', + decimalCharacter: ',', + unformatOnSubmit: true, + decimalPlacesShownOnFocus: 2, + decimalPlacesShownOnBlur: 2, + }); + + if(total.getNumber() == null || total.getNumber() == "" || total.getNumber() == 0) { + Swal.fire({ + title: 'Error', + text: "No se puede conformar una factura rectificativa con importe 0€.", + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + return; + } + + + const id = window.location.href.split('/').pop(); + const fechaVencimiento = fechaVencimientoRectificativa.val(); + + $.post('/facturas/conformarFactura', { + factura_id: id, + fecha: fechaVencimiento, + total: total.getNumber(), + }, function (response) { + if (response.status) { + + Swal.fire({ + text: response.message, + icon: 'success', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }).then(() => { + window.location.reload(); + }); + } else { + Swal.fire({ + title: 'Error', + text: response.message, + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + } + }).fail(() => { + Swal.fire({ + title: 'Error', + text: 'No se pudo conformar la factura.', + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + }); + } + }); + + }) + + } +}) \ No newline at end of file From ce124cb38a4f335805d56724c54b966552270c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Wed, 14 May 2025 13:49:08 +0200 Subject: [PATCH 068/127] resuelto --- ci4/app/Models/Presupuestos/PresupuestoModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci4/app/Models/Presupuestos/PresupuestoModel.php b/ci4/app/Models/Presupuestos/PresupuestoModel.php index d2cf953d..dc594bae 100755 --- a/ci4/app/Models/Presupuestos/PresupuestoModel.php +++ b/ci4/app/Models/Presupuestos/PresupuestoModel.php @@ -453,7 +453,7 @@ class PresupuestoModel extends \App\Models\BaseModel 'comparador_json_data' => $this->generateJson($data), - 'faja_color' => is_array($data['faja']) ? 1 : 0, + 'faja_color' => is_array($data['faja']) && count($data['faja'])>0 ? 1 : 0, 'solapas_ancho_faja_color' => is_array($data['faja']) && $data['faja'] !== [] ? $data['faja']['solapas'] : 60, 'alto_faja_color' => is_array($data['faja']) && $data['faja'] !== [] ? $data['faja']['alto'] : 50, From 760b9bdd940ffa5b3ed2735b8378ba869c2f53da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Wed, 14 May 2025 13:57:33 +0200 Subject: [PATCH 069/127] =?UTF-8?q?arreglado=20tambi=C3=A9n=20problema=20d?= =?UTF-8?q?e=20sobrecubierta=20en=20importador=20rama?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci4/app/Controllers/Importadores/ImportadorCatalogo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php index d3797f3e..23df0636 100644 --- a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php +++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php @@ -216,7 +216,7 @@ class ImportadorCatalogo extends BaseResourceController // Sobrecubierta $sobrecubierta = []; - if (!is_null($libro->sobrecubierta_paginas)) { + if (!is_null($libro->sobrecubierta_paginas) && $libro->sobrecubierta_paginas != 0) { $sobrecubierta['papel'] = $libro->sobrecubierta_papel_id; $sobrecubierta['gramaje'] = $libro->sobrecubierta_gramaje; $sobrecubierta['solapas'] = $libro->sobrecubierta_solapas; From 22bdb9b960f2eef113b0b47f9be31a2533577190 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Wed, 14 May 2025 20:38:39 +0200 Subject: [PATCH 070/127] Cambiado pais por referencia cliente en el buscador de presupuestos --- ci4/app/Language/es/Presupuestos.php | 2 +- ci4/app/Models/Presupuestos/BuscadorModel.php | 5 ++--- .../vuexy/form/presupuestos/buscador/viewBuscadorList.php | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ci4/app/Language/es/Presupuestos.php b/ci4/app/Language/es/Presupuestos.php index 238dac47..f23b687b 100755 --- a/ci4/app/Language/es/Presupuestos.php +++ b/ci4/app/Language/es/Presupuestos.php @@ -61,7 +61,7 @@ return [ 'coleccion' => 'Colección', 'numeroEdicion' => 'Número de edición', 'isbn' => 'ISBN', - 'referenciaCliente' => 'Referencia del cliente', + 'referenciaCliente' => 'Referencia cliente', 'referenciaCliente2' => 'Referencia', 'papelFormatoId' => "Tamaño", 'papelFormatoPersonalizado' => 'Tamaño personalizado', diff --git a/ci4/app/Models/Presupuestos/BuscadorModel.php b/ci4/app/Models/Presupuestos/BuscadorModel.php index df051c59..8eb6af36 100755 --- a/ci4/app/Models/Presupuestos/BuscadorModel.php +++ b/ci4/app/Models/Presupuestos/BuscadorModel.php @@ -20,7 +20,7 @@ class BuscadorModel extends \App\Models\BaseModel 3 => "t2.nombre", 4 => "t3.first_name", 5 => "t1.titulo", - 6 => "t5.nombre", + 6 => "t1.referencia_cliente", 7 => "t1.inc_rei", 8 => "t1.paginas", 9 => "t1.tirada", @@ -127,13 +127,12 @@ class BuscadorModel extends \App\Models\BaseModel ->select( "t1.id AS id, t1.created_at AS fecha, t7.codigo as codigo, t2.nombre AS cliente, CONCAT(t3.first_name, ' ', t3.last_name) AS comercial, t1.titulo AS titulo, - t5.nombre AS pais, t1.inc_rei AS inc_rei, t1.paginas AS paginas, t1.tirada AS tirada, + t1.referencia_cliente AS refCliente, t1.inc_rei AS inc_rei, t1.paginas AS paginas, t1.tirada AS tirada, t1.total_presupuesto AS total_presupuesto, t1.total_presupuesto AS total_presupuesto, t6.estado AS estado" ); $builder->join("clientes t2", "t1.cliente_id = t2.id", "left"); $builder->join("users t3", "t2.comercial_id = t3.id", "left"); - $builder->join("lg_paises t5", "t1.pais_id = t5.id", "left"); $builder->join("presupuesto_estados t6", "t1.estado_id = t6.id", "left"); $builder->join("tipos_presupuestos t7", "t1.tipo_impresion_id = t7.id", "left"); diff --git a/ci4/app/Views/themes/vuexy/form/presupuestos/buscador/viewBuscadorList.php b/ci4/app/Views/themes/vuexy/form/presupuestos/buscador/viewBuscadorList.php index 56b9a9ef..72ed1f0f 100755 --- a/ci4/app/Views/themes/vuexy/form/presupuestos/buscador/viewBuscadorList.php +++ b/ci4/app/Views/themes/vuexy/form/presupuestos/buscador/viewBuscadorList.php @@ -23,7 +23,7 @@
- + @@ -245,7 +245,7 @@ theTable = $('#tableOfPresupuestos').DataTable({ { 'data': 'cliente' }, { 'data': 'comercial' }, { 'data': 'titulo' }, - { 'data': 'pais' }, + { 'data': 'refCliente' }, { 'data': 'inc_rei' }, { 'data': 'paginas',render : (d) => `${d}` }, { 'data': 'tirada' ,render : (d) => `${d}` }, From 359e13260fe21150ab474d6e77b5bac88760eaa5 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Thu, 15 May 2025 18:02:32 +0200 Subject: [PATCH 071/127] Fixed campo secret para obtener el email --- ci4/app/Models/Sistema/ActivityModel.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ci4/app/Models/Sistema/ActivityModel.php b/ci4/app/Models/Sistema/ActivityModel.php index 21f22d47..fa0704f3 100755 --- a/ci4/app/Models/Sistema/ActivityModel.php +++ b/ci4/app/Models/Sistema/ActivityModel.php @@ -20,7 +20,7 @@ class ActivityModel extends BaseModel const SORTABLE = [ 1 => "t1.id", - 2 => "t2.username", + 2 => "t3.secret", 3 => "t1.level", 4 => "t1.event", 5 => "t1.ip", @@ -55,10 +55,17 @@ class ActivityModel extends BaseModel $builder = $this->db ->table($this->table . " t1") ->select( - "t1.id AS id, t2.username AS user, t1.level AS level, t1.event AS event, t1.ip AS ip, t1.os AS os, - t1.browser AS browser, t1.created_at AS created_at" + "t1.id AS id, + t3.secret AS user, + t1.level AS level, + t1.event AS event, + t1.ip AS ip, + t1.os AS os, + t1.browser AS browser, + t1.created_at AS created_at" ) ->join("users t2", "t1.user_id = t2.id", "left") + ->join("auth_identities t3", "t3.user_id = t2.id AND t3.type = 'email_password'", "left") ->orderBy('t1.created_at', 'DESC'); return empty($search) @@ -66,7 +73,7 @@ class ActivityModel extends BaseModel : $builder ->groupStart() ->like("t1.id", $search) - ->orLike("t2.username", $search) + ->orLike("t3.secret", $search) ->orLike("t1.level", $search) ->orLike("t1.event", $search) ->orLike("t1.ip", $search) From decdcf3703f97e41ffcd76e3d29a857ff731fa4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Thu, 15 May 2025 23:55:09 +0200 Subject: [PATCH 072/127] trabajando en la lista de envios proximos --- ci4/app/Config/Routes.php | 1 + .../Logistica/LogisticaController.php | 19 + ci4/app/Language/es/Logistica.php | 4 + ci4/app/Language/es/Produccion.php | 1 + ci4/app/Models/Logistica/EnvioLineaModel.php | 3 +- ci4/app/Services/LogisticaService.php | 38 +- .../form/logistica/viewEnvioEditForm.php | 437 ++++++++++-------- .../maquinista/viewMaquinistaMaquinaTarea.php | 3 + .../maquinista/maquinistaTareaView.js | 47 ++ .../js/safekat/pages/logistica/envioEdit.js | 113 ++++- 10 files changed, 453 insertions(+), 213 deletions(-) diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 03ad8f11..4e1c1a81 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -871,6 +871,7 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi $routes->get('selectForNewEnvio', 'LogisticaController::findForNewEnvio'); $routes->get('selectDireccionForEnvio', 'LogisticaController::selectDireccionForEnvio'); $routes->post('imprimirEtiquetas', 'LogisticaController::imprimirEtiquetas'); + $routes->post('ficharEmbalaje', 'LogisticaController::ficharEmbalaje'); $routes->get('listAlbaranes', 'LogisticaController::listAlbaranes', ['as' => 'albaranesList']); }); diff --git a/ci4/app/Controllers/Logistica/LogisticaController.php b/ci4/app/Controllers/Logistica/LogisticaController.php index b69b0f4c..4ffd0733 100755 --- a/ci4/app/Controllers/Logistica/LogisticaController.php +++ b/ci4/app/Controllers/Logistica/LogisticaController.php @@ -132,6 +132,8 @@ class LogisticaController extends BaseController $result = $query->orderBy("name", "asc")->get()->getResultObject(); + $query = model('App\Models\Logistica\EnvioModel')->db->getLastQuery(); + return $this->response->setJSON($result); } else { return $this->failUnauthorized('Invalid request', 403); @@ -392,6 +394,17 @@ class LogisticaController extends BaseController } } + public function ficharEmbalaje() + { + if ($this->request->isAJAX()) { + + $ids = $this->request->getPost('ids') ?? []; + $result = LogisticaService::ficharEmbalaje($ids); + return $this->response->setJSON($result); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } public function datatable_enviosEdit($idEnvio) { @@ -406,6 +419,12 @@ class LogisticaController extends BaseController return ''; } ) + ->edit( + "ordenTrabajo", + function ($row, $meta) { + return '' . $row->ordenTrabajo . ''; + } + ) ->edit( "pedido", function ($row, $meta) { diff --git a/ci4/app/Language/es/Logistica.php b/ci4/app/Language/es/Logistica.php index 0ef3e713..be9a91d8 100755 --- a/ci4/app/Language/es/Logistica.php +++ b/ci4/app/Language/es/Logistica.php @@ -44,6 +44,7 @@ return [ 'totales' => 'Totales', 'cajas' => 'Cajas', + 'ordenTrabajo' => 'OT', 'pedido' => 'Pedido', 'presupuesto' => 'Presupuesto', 'unidadesEnvio' => 'Unidades envío', @@ -62,6 +63,7 @@ return [ 'codigoSeguimiento' => 'Código de seguimiento', 'empresaMensajería' => 'Empresa de mensajería', + 'ficharEmbalaje' => 'Fichar embalaje', 'finalizarEnvio' => 'Finalizar envío', 'finalizarEnvioYOTs' => 'Finalizar envío y OTS', @@ -90,6 +92,7 @@ return [ 'errorInsertarEtiqueta' => 'Error al insertar la etiqueta', 'noEtiqueta' => 'No se ha encontrado la etiqueta', 'noEtiquetaLineas' => 'No se han encontrado líneas de etiqueta', + 'noLineas' => 'No se ha seleccionado ninguna línea', ], 'success' => [ 'finalizado' => 'El envío se ha finalizado correctamente', @@ -101,6 +104,7 @@ return [ 'comentariosUpdated' => 'Comentarios actualizados correctamente', 'successReordenarCajas' => 'Cajas reordenadas correctamente', 'imprimirEtiquetas' => 'Etiquetas impresas correctamente', + 'successFicharEmbalaje' => 'Embalaje fichado correctamente', ], ]; \ No newline at end of file diff --git a/ci4/app/Language/es/Produccion.php b/ci4/app/Language/es/Produccion.php index 728920c0..3d990871 100755 --- a/ci4/app/Language/es/Produccion.php +++ b/ci4/app/Language/es/Produccion.php @@ -182,6 +182,7 @@ return [ 'duplicate_estado_tarea_progress' => "Último estado de la tarea repetido", 'task_already_finished' => "La tarea se ha marcado como finalizada.", 'print_label' => "Imprimir etiqueta", + 'fichar_embalaje' => "Fichar embalaje", 'click_init' => "Clicks al inicio", 'click_end' => "Clicks al final", "comentarios" => "Comentarios", diff --git a/ci4/app/Models/Logistica/EnvioLineaModel.php b/ci4/app/Models/Logistica/EnvioLineaModel.php index a50709d3..76ae7b9b 100644 --- a/ci4/app/Models/Logistica/EnvioLineaModel.php +++ b/ci4/app/Models/Logistica/EnvioLineaModel.php @@ -35,7 +35,7 @@ class EnvioLineaModel extends Model $builder = $this->db ->table($this->table . " t1") ->select( - "t1.id, t1.pedido_id as pedido, t3.id as presupuesto, + "t1.id, t1.pedido_id as pedido, t3.id as presupuesto, t4.id as ordenTrabajo, t3.titulo as titulo, t1.unidades_envio as unidadesEnvio, t1.unidades_envio as unidadesEnvioRaw, t1.unidades_total as unidadesTotal, t2.tipo_envio as tipo_envio, IFNULL(( @@ -59,6 +59,7 @@ class EnvioLineaModel extends Model ); $builder->join("envios t2", "t1.envio_id = t2.id", "left"); $builder->join("presupuestos t3", "t1.presupuesto_id = t3.id", "left"); + $builder->join("ordenes_trabajo t4", "t1.pedido_id = t4.pedido_id", "left"); $builder->where("t1.envio_id", $envio_id); diff --git a/ci4/app/Services/LogisticaService.php b/ci4/app/Services/LogisticaService.php index cb4fb1b5..6d5f91b9 100644 --- a/ci4/app/Services/LogisticaService.php +++ b/ci4/app/Services/LogisticaService.php @@ -57,7 +57,8 @@ class LogisticaService ->join('orden_trabajo_dates ot_dates', 'ot_dates.orden_trabajo_id = ot.id') ->whereIn('pr.id', $presupuestoIds) ->whereIn('p.estado', ['finalizado', 'produccion']) - ->where('ot_dates.embalaje_at IS NOT NULL') + ->where('p.fecha_encuadernado IS NOT NULL') + ->where('DATE(p.fecha_encuadernado) <=', date('Y-m-d')) ->where("NOT EXISTS ( SELECT 1 FROM envios_lineas el @@ -103,16 +104,15 @@ class LogisticaService ->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.embalaje_at IS NOT NULL') + ->where('p.fecha_encuadernado IS NOT NULL') + ->where('DATE(p.fecha_encuadernado) <=', date('Y-m-d')) ->groupBy('pl.id'); // 4. Envolver y filtrar por unidades pendientes $builder = $db->table("({$subBuilder->getCompiledSelect(false)}) AS sub"); $builder->select('id, name'); $builder->where('cantidad > unidades_enviadas'); - $builder->orderBy('name', 'ASC'); return $builder; } @@ -539,6 +539,13 @@ class LogisticaService $ot = $otModel->where('pedido_id', $linea->pedido_id) ->first(); $ps = (new ProductionService())->init($ot->id); + $date = $ps->getOrdenTrabajo()->dates()->embalaje_at; + if (is_null($date) || empty($date)) { + $ps->updateOrdenTrabajoDate([ + "name" => "embalaje_at", + "embalaje_at" => date('Y-m-d H:i:s') + ]); + } $ps->updateOrdenTrabajoDate([ "name" => "envio_at", "envio_at" => date('Y-m-d H:i:s') @@ -572,6 +579,29 @@ class LogisticaService return $data_return; } + public static function ficharEmbalaje($ids = null) + { + + if (is_null($ids) || empty($ids) || count($ids) == 0) { + return [ + 'status' => false, + 'message' => lang('Logistica.errors.noLineas'), + ]; + } + + for ($index = 0; $index < count($ids); $index++) { + $ps = (new ProductionService())->init($ids[$index]); + $ps->updateOrdenTrabajoDate([ + "name" => "embalaje_at", + "embalaje_at" => date('Y-m-d') + ]); + } + return [ + 'status' => true, + 'message' => lang('Logistica.success.successFicharEmbalaje'), + ]; + } + public static function generateEtiquetasTitulos($envio, $lineas, $printer, $cajas) { $data = [ diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php index 7c63bd17..27eecf8c 100644 --- a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php @@ -10,7 +10,7 @@

- tipo_envio == 'ferro_prototipo') ? 'FERRO':'' ?> + tipo_envio == 'ferro_prototipo') ? 'FERRO' : '' ?> finalizado == 0) ? '' : 'FINALIZADO' ?>

@@ -114,7 +114,7 @@
- finalizado == 0 && $envioEntity->tipo_envio=='estandar'): ?> + finalizado == 0 && $envioEntity->tipo_envio == 'estandar'): ?>

@@ -130,6 +130,7 @@

+
-
-
- - - +
- -
-
-

- -

- -
-
-
-

-
-
-
- -
- finalizado == 0 && $envioEntity->tipo_envio=='estandar'): ?> -
- -
- -
- -
-
- -
- -
-
- - +
+
Java
+
PHP
+
Lua
+
SQL
+
Java
+
PHP
+
Lua
+
SQL
+
Java
+
PHP
+
Lua
+
SQL
+
Java
+
PHP
+
Lua
+
SQL
+
- -
-
- -
ReferenciaTítuloTamañoPáginasTiradaInteriorNotasAcciones
ReferenciaTítuloTamañoPáginasTiradaInteriorNotasAcciones
- - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
-
- - -
-
-
- - -
-
- -
- - - -
- + -
- -
-

- -

- -
-
- - -
- -
-
-

- +

-
-
- - finalizado == 0) ? '' : 'readonly' ?> - value="codigo_seguimiento)) ?>"> -
-
- - finalizado == 0): ?> - - - - -
- finalizado == 0): ?> -
- +
+
+
+

- tipo_envio=='estandar'): ?> -
- +
+
+ +
+ finalizado == 0 && $envioEntity->tipo_envio == 'estandar'): ?> +
+ +
+ +
+ +
+
+ +
+
+ +
+ +
+
+ + +
+
+
- - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+ + +
+
+
+ + +
+
+ +
+ + + +
+
+
-
+
+ +
+

+ +

+ +
+
+ + +
+ +
+
+
+ +
+
+

+ +

+ +
+
+ + finalizado == 0) ? '' : 'readonly' ?> + value="codigo_seguimiento)) ?>"> +
+
+ + finalizado == 0): ?> + + + + +
+ finalizado == 0): ?> +
+ +
+ tipo_envio == 'estandar'): ?> +
+ +
+ + +
+
+
+ +
- -endSection() ?> + endSection() ?> -section('css') ?> - - - -"> + section('css') ?> + + + + "> + " /> -endSection() ?> + endSection() ?> -section('additionalExternalJs') ?> - - - - -endSection() ?> \ No newline at end of file + section('additionalExternalJs') ?> + + + + + endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTarea.php b/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTarea.php index 66d37d4d..73c261f1 100644 --- a/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTarea.php +++ b/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTarea.php @@ -48,6 +48,9 @@
+
+ +
diff --git a/httpdocs/assets/js/safekat/pages/configuracion/maquinista/maquinistaTareaView.js b/httpdocs/assets/js/safekat/pages/configuracion/maquinista/maquinistaTareaView.js index 82d2e321..574b9b32 100644 --- a/httpdocs/assets/js/safekat/pages/configuracion/maquinista/maquinistaTareaView.js +++ b/httpdocs/assets/js/safekat/pages/configuracion/maquinista/maquinistaTareaView.js @@ -14,6 +14,7 @@ class MaquinistaTareaView { this.tareaCardClass = '.tarea-card-action-block' this.inputClick = $('.ot-tarea-click') this.btnPrintLabels = this.item.find('#btn-print-labels') + this.btnFicharEmbalaje = this.item.find('#btn-fichar-embalaje') } init() { this.actionButtons.on('click', this.eventActionButton.bind(this)) @@ -22,6 +23,7 @@ class MaquinistaTareaView { this.handleGetTareaProgress(); this.inputClick.on('input', this.handleUpdateClickInput.bind(this)) this.btnPrintLabels.on('click', this.handlePrintLabels.bind(this)) + this.btnFicharEmbalaje.on('click', this.handleFicharEmbalaje.bind(this)) } eventActionButton(event) { @@ -301,6 +303,51 @@ class MaquinistaTareaView { }); } + handleFicharEmbalaje() { + const ot_id = [$('#otId').html()]; + $.post('/logistica/ficharEmbalaje', { + ids: ot_id, + }, function (response) { + if (response.status) { + Swal.fire({ + text: response.message, + icon: 'success', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + } else { + Swal.fire({ + title: 'Error', + text: response.message, + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + table.ajax.reload(); + } + }).fail(() => { + Swal.fire({ + title: 'Error', + text: 'No se pudo realizar el fichaje.', + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + table.ajax.reload(); + }); + } } export default MaquinistaTareaView; \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js b/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js index 4faf0457..63c6c3e3 100644 --- a/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js +++ b/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js @@ -7,6 +7,7 @@ class EnvioEdit { constructor() { this.tableCols = [ { data: "rowSelected" }, + { data: "ordenTrabajo" }, { data: "pedido" }, { data: "presupuesto" }, { data: "titulo" }, @@ -42,6 +43,12 @@ class EnvioEdit { this.proveedor.init(); } + if ($("#proximosEnvios").length) { + new PerfectScrollbar(document.getElementById('proximosEnvios'), { + wheelPropagation: false + }); + } + this.table = $('#tableLineasEnvio').DataTable({ processing: true, serverSide: true, @@ -84,11 +91,11 @@ class EnvioEdit { "searchable": false, }, { - "targets": [1, 2, 4, 5, 6], + "targets": [1, 2, 4, 5, 6, 7], "className": "text-center", }, { - targets: [7, 8, 9], + targets: [8, 9, 10], visible: false } ] @@ -121,7 +128,7 @@ class EnvioEdit { } const idEnvio = $('#id').val(); let num_cajas = this.cajas.val(); - if(ids.length != table.rows().count()){ + if (ids.length != table.rows().count()) { // se preguntará el numero de cajas en un swal con un input para obtener el valor Swal.fire({ title: 'Atención!', @@ -146,7 +153,7 @@ class EnvioEdit { } }); } - else{ + else { this._imprimirEtiquetas(idEnvio, ids, num_cajas); } }); @@ -485,9 +492,14 @@ class EnvioEdit { }); }); + $('#ficharEmbalaje').on('click', (e) => { + this._ficharEmbalajeLineas(); + }); + this._getAlbaranes(); } + _imprimirEtiquetas(envio_id, ids, num_cajas) { $.post('/logistica/imprimirEtiquetas', { @@ -510,7 +522,7 @@ class EnvioEdit { }, buttonsStyling: false }).then(() => { - if(response.data){ + if (response.data) { // show xml in a new tab const blob = new Blob([response.data], { type: 'application/xml' }); const url = URL.createObjectURL(blob); @@ -520,7 +532,7 @@ class EnvioEdit { a.click(); URL.revokeObjectURL(url); a.remove(); - + } }); } @@ -671,6 +683,95 @@ class EnvioEdit { }); } + + _ficharEmbalajeLineas() { + const table = this.table; + const selectedRows = table.rows({ page: 'current' }).nodes().filter((node) => { + const checkbox = $(node).find('.checkbox-linea-envio'); + return checkbox.is(':checked'); + }); + const ids = selectedRows.map((node) => { + const rowData = table.row(node).data(); + const parser = new DOMParser(); + const doc = parser.parseFromString(rowData.ordenTrabajo, 'text/html'); + return doc.body.textContent.trim(); // extrae solo el texto dentro del + }).toArray(); + + if (ids.length > 0) { + Swal.fire({ + title: 'Fichar embalaje', + text: '¿Está seguro de fichar el embalaje de las líneas seleccionadas?', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Sí', + cancelButtonText: 'Cancelar', + customClass: { + confirmButton: 'btn btn-danger me-1', + cancelButton: 'btn btn-secondary' + }, + buttonsStyling: false + }).then((result) => { + if (result.isConfirmed) { + $.post('/logistica/ficharEmbalaje', { + ids: ids + }, function (response) { + if (response.status) { + Swal.fire({ + text: response.message, + icon: 'success', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + } else { + Swal.fire({ + title: 'Error', + text: response.message, + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + table.ajax.reload(); + } + }).fail(() => { + Swal.fire({ + title: 'Error', + text: 'No se pudo realizar el fichaje.', + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + table.ajax.reload(); + }); + } + }); + } else { + Swal.fire({ + title: 'Sin filas seleccionadas', + text: 'Marca al menos una línea para eliminarla.', + icon: 'info', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + } + } + + _deleteLineas() { const table = this.table; const selectedRows = table.rows({ page: 'current' }).nodes().filter((node) => { From 438000ebad7ee46c2e651939fbae44e1e0dea303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 19 May 2025 18:41:48 +0200 Subject: [PATCH 073/127] hecho lo de proximos envios --- ci4/app/Config/Routes.php | 2 + .../Logistica/LogisticaController.php | 58 ++- ci4/app/Language/es/Logistica.php | 1 + .../Models/OrdenTrabajo/OrdenTrabajoModel.php | 21 + ci4/app/Services/LogisticaService.php | 73 +++ .../form/logistica/viewEnvioEditForm.php | 473 +++++++++--------- .../js/safekat/pages/logistica/envioEdit.js | 47 +- 7 files changed, 423 insertions(+), 252 deletions(-) diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 4e1c1a81..f94097e3 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -765,6 +765,7 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func $routes->get('tareas/datatable/(:num)', 'Ordentrabajo::tareas_datatable/$1', ['as' => 'datatableTareasOrdenTrabajo']); $routes->get('maquinas/ots/datatable/(:num)','Ordentrabajo::datatable_maquina_ordenes_trabajo/$1'); $routes->get('maquinas/ots/(:num)','Ordentrabajo::get_maquina_ots/$1'); + /**====================== * UPDATES *========================**/ @@ -872,6 +873,7 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi $routes->get('selectDireccionForEnvio', 'LogisticaController::selectDireccionForEnvio'); $routes->post('imprimirEtiquetas', 'LogisticaController::imprimirEtiquetas'); $routes->post('ficharEmbalaje', 'LogisticaController::ficharEmbalaje'); + $routes->get('datatableProximosEnvios/(:num)', 'LogisticaController::datatable_proximosEnvios/$1'); $routes->get('listAlbaranes', 'LogisticaController::listAlbaranes', ['as' => 'albaranesList']); }); diff --git a/ci4/app/Controllers/Logistica/LogisticaController.php b/ci4/app/Controllers/Logistica/LogisticaController.php index 4ffd0733..23c4d3de 100755 --- a/ci4/app/Controllers/Logistica/LogisticaController.php +++ b/ci4/app/Controllers/Logistica/LogisticaController.php @@ -98,7 +98,8 @@ class LogisticaController extends BaseController return view(static::$viewPath . 'viewImpresionEtiquetas', $viewData); } - public function listAlbaranes(){ + public function listAlbaranes() + { $viewData = [ 'currentModule' => static::$controllerSlug, 'boxTitle' => lang('Albaran.albaranes'), @@ -117,7 +118,7 @@ class LogisticaController extends BaseController $tipo_envio = $this->request->getGet('tipo_envio') ?? 'estandar'; - if($tipo_envio == 'ferro_prototipo'){ + if ($tipo_envio == 'ferro_prototipo') { $query = LogisticaService::findForNewEnvioFerro(); } else { $query = LogisticaService::findForNewEnvio(); @@ -140,16 +141,17 @@ class LogisticaController extends BaseController } } - public function selectDireccionForEnvio(){ + public function selectDireccionForEnvio() + { if ($this->request->isAJAX()) { $ot = $this->request->getGet('ot_id'); - if($ot == null || $ot == 0){ + if ($ot == null || $ot == 0) { return []; } $searchVal = $this->request->getGet("q") ?? ""; $result = LogisticaService::findDireccionesNewEnvio($ot, $searchVal); - + return $this->response->setJSON($result); } else { return $this->failUnauthorized('Invalid request', 403); @@ -187,12 +189,12 @@ class LogisticaController extends BaseController public function imprimirEtiquetas() { if ($this->request->isAJAX()) { - $envio_id = $this->request->getPost('envio_id'); + $envio_id = $this->request->getPost('envio_id'); $ids = $this->request->getPost('envio_lineas'); $cajas = $this->request->getPost('cajas'); $printer_id = $this->request->getPost('printer_id'); - if($cajas == null || $cajas == 0){ + if ($cajas == null || $cajas == 0) { return $this->response->setJSON([ 'status' => false, 'message' => 'Cajas no válidas' @@ -204,7 +206,7 @@ class LogisticaController extends BaseController ->join('clientes', 'clientes.id = envios.cliente_id', 'left') ->where('envios.id', $envio_id) ->first(); - if($envio == null){ + if ($envio == null) { return $this->response->setJSON([ 'status' => false, 'message' => 'Envio no válido' @@ -215,7 +217,7 @@ class LogisticaController extends BaseController $lineas = $model->select('envios_lineas.*, presupuestos.titulo as titulo, presupuestos.referencia_cliente as referencia_cliente') ->join('presupuestos', 'presupuestos.id = envios_lineas.presupuesto_id', 'left') ->whereIn('envios_lineas.id', $ids)->findAll(); - if($lineas == null){ + if ($lineas == null) { return $this->response->setJSON([ 'status' => false, 'message' => 'Lineas no válidas' @@ -228,7 +230,7 @@ class LogisticaController extends BaseController ->where('id', $printer_id) ->orderBy('name', 'asc') ->first(); - if($impresora == null){ + if ($impresora == null) { return $this->response->setJSON([ 'status' => false, 'message' => 'Impresora no válida' @@ -332,14 +334,14 @@ class LogisticaController extends BaseController if (empty($envioEntity)) { return redirect()->to(base_url('logistica/selectEnvios/simple'))->with('error', lang('Logistica.errors.noEnvio')); } - + $modelProveedor = model('App\Models\Compras\ProveedorModel'); $proveedor = $modelProveedor->select('id, nombre') ->where('deleted_at', null) ->where('id', $envioEntity->proveedor_id) ->orderBy('nombre', 'asc') ->first(); - if(!empty($proveedor)){ + if (!empty($proveedor)) { $envioEntity->proveedor_nombre = $proveedor->nombre; } @@ -386,7 +388,7 @@ class LogisticaController extends BaseController $id = $this->request->getPost('id') ?? null; $finalizar_ots = $this->request->getPost('finalizar_ots') ?? false; - + $result = LogisticaService::finalizarEnvio($id, $finalizar_ots); return $this->response->setJSON($result); } else { @@ -439,17 +441,35 @@ class LogisticaController extends BaseController )->edit( "unidadesEnvio", function ($row, $meta) { - if($row->finalizado == 1 || $row->tipo_envio == 'ferro_prototipo'){ + if ($row->finalizado == 1 || $row->tipo_envio == 'ferro_prototipo') { return $row->unidadesEnvio; } return ''; + data-id="' . $row->id . '" data-name="unidades_envio" value="' . $row->unidadesEnvio . '">'; } ); return $result->toJson(returnAsObject: true); } + public function datatable_proximosEnvios($envio_id = null) + { + $q = LogisticaService::findNextEnvios($envio_id); + + $result = DataTable::of($q) + ->edit( + "ot", + function ($row, $meta) { + return '' . $row->ot . ''; + } + ); + + $result = $result->toJson(returnAsObject: true); + $query = model('App\Models\Logistica\EnvioModel')->db->getLastQuery(); + return $result; + + } + public function setCajaLinea() { @@ -490,7 +510,7 @@ class LogisticaController extends BaseController $fieldName = $this->request->getPost('name'); $fieldValue = $this->request->getPost('value'); - if (!$id || !$fieldName || ($fieldName=='unidades_envio' && !$fieldValue)) { + if (!$id || !$fieldName || ($fieldName == 'unidades_envio' && !$fieldValue)) { return $this->response->setJSON([ 'status' => false, 'message' => 'Datos inválidos' @@ -499,7 +519,7 @@ class LogisticaController extends BaseController $model = model('App\Models\Logistica\EnvioLineaModel'); $updated = $model->update($id, [ - "" . $fieldName => $fieldValue==""? null: $fieldValue, + "" . $fieldName => $fieldValue == "" ? null : $fieldValue, ]); return $this->response->setJSON([ @@ -522,7 +542,7 @@ class LogisticaController extends BaseController $model = model('App\Models\Logistica\EnvioModel'); $updated = $model->update($id, [ - "codigo_seguimiento" => $fieldValue==""? null: $fieldValue, + "codigo_seguimiento" => $fieldValue == "" ? null : $fieldValue, ]); return $this->response->setJSON([ @@ -545,7 +565,7 @@ class LogisticaController extends BaseController $model = model('App\Models\Logistica\EnvioModel'); $updated = $model->update($id, [ - "proveedor_id" => $fieldValue==""? null: $fieldValue, + "proveedor_id" => $fieldValue == "" ? null : $fieldValue, ]); return $this->response->setJSON([ diff --git a/ci4/app/Language/es/Logistica.php b/ci4/app/Language/es/Logistica.php index be9a91d8..4213a476 100755 --- a/ci4/app/Language/es/Logistica.php +++ b/ci4/app/Language/es/Logistica.php @@ -60,6 +60,7 @@ return [ 'selectAll' => 'Seleccionar todo', 'peso' => 'Peso (kg): ', 'unidadesTotalesFooter' => 'Unidades:', + 'fechaEncuadernado' => 'Fecha encuadernado', 'codigoSeguimiento' => 'Código de seguimiento', 'empresaMensajería' => 'Empresa de mensajería', diff --git a/ci4/app/Models/OrdenTrabajo/OrdenTrabajoModel.php b/ci4/app/Models/OrdenTrabajo/OrdenTrabajoModel.php index e28a7e1b..5c81a5ab 100755 --- a/ci4/app/Models/OrdenTrabajo/OrdenTrabajoModel.php +++ b/ci4/app/Models/OrdenTrabajo/OrdenTrabajoModel.php @@ -143,4 +143,25 @@ class OrdenTrabajoModel extends Model ->groupBy('orden_trabajo_tareas.id'); return $query; } + + public function queryProximosEnvios() + { + $query = $this->builder() + ->select([ + 'ordenes_trabajo.id as ot', + 'orden_trabajo_dates.encuadernacion_at as fechaEncuadernado', + ]) + ->join('pedidos', 'pedidos.id = ordenes_trabajo.pedido_id', 'left') + ->join('pedidos_linea', 'pedidos.id = pedidos_linea.pedido_id', 'left') + ->join('presupuestos', 'presupuestos.id = pedidos_linea.presupuesto_id', 'left') + ->join('presupuesto_direcciones', 'presupuestos.id = presupuesto_direcciones.presupuesto_id', 'left') + ->join('orden_trabajo_dates', 'orden_trabajo_dates.orden_trabajo_id = ordenes_trabajo.id', 'left') + ->where('ordenes_trabajo.deleted_at', null) + ->where('orden_trabajo_dates.encuadernacion_at !=', null) + + //->where('orden_trabajo_dates.fecha_encuadernado_at >=', 0) + //->where('ordenes_trabajo.fecha_entrega_warning >=', date("Y-m-d H:i:s")) + ->groupBy('ordenes_trabajo.id'); + return $query; + } } diff --git a/ci4/app/Services/LogisticaService.php b/ci4/app/Services/LogisticaService.php index 6d5f91b9..5e2fe8e1 100644 --- a/ci4/app/Services/LogisticaService.php +++ b/ci4/app/Services/LogisticaService.php @@ -79,6 +79,79 @@ class LogisticaService return $builder; } + public static function findNextEnvios(int $envio_id) + { + $db = \Config\Database::connect(); + + // 1. Dirección del envío actual + $envio = $db->table('envios')->select('direccion')->where('id', $envio_id)->get()->getRow(); + if (!$envio) { + return $db->table('(SELECT NULL AS id, NULL AS name) AS empty')->where('1 = 0'); + } + + $direccionNormalizada = str_replace(' ', '', strtolower(trim($envio->direccion))); + $direccionSQL = $db->escape($direccionNormalizada); + + // 2. Obtener presupuestos con esa dirección + $presupuestosConEsaDireccion = $db->table('presupuesto_direcciones') + ->select('presupuesto_id') + ->where("REPLACE(LOWER(TRIM(direccion)), ' ', '') = $direccionSQL", null, false) + ->get() + ->getResultArray(); + + $presupuestoIds = array_column($presupuestosConEsaDireccion, 'presupuesto_id'); + if (empty($presupuestoIds)) { + return $db->table('(SELECT NULL AS id, NULL AS name) AS empty')->where('1 = 0'); + } + + $hoy = date('Y-m-d'); + $sieteDiasDespues = date('Y-m-d', strtotime('+7 days')); + + // 3. Subconsulta principal + $subBuilder = $db->table('pedidos_linea pl') + ->select(" + ot.id AS ot, + DATE(p.fecha_encuadernado) as fechaEncuadernado, + ( + SELECT IFNULL(SUM(el.unidades_envio), 0) + FROM envios_lineas el + JOIN envios e ON e.id = el.envio_id + WHERE el.pedido_id = p.id + AND el.presupuesto_id = pr.id + AND REPLACE(LOWER(TRIM(e.direccion)), ' ', '') = $direccionSQL + AND (e.finalizado = 1 OR e.id = $envio_id) + ) AS unidades_enviadas, + pd.cantidad AS cantidad + ") + ->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('pr.id', $presupuestoIds) + ->whereIn('p.estado', ['finalizado', 'produccion']) + ->where('p.fecha_encuadernado IS NOT NULL') + ->where('DATE(p.fecha_encuadernado) >=', $hoy) + ->where('DATE(p.fecha_encuadernado) <=', $sieteDiasDespues) + ->where("NOT EXISTS ( + SELECT 1 + FROM envios_lineas el + WHERE el.envio_id = $envio_id + AND el.pedido_id = p.id + AND el.presupuesto_id = pr.id + GROUP BY el.pedido_id, el.presupuesto_id + HAVING SUM(el.unidades_envio) >= pd.cantidad + )", null, false) + ->groupBy('pl.id'); + + // 4. Envolver y filtrar por unidades pendientes + $builder = $db->table("({$subBuilder->getCompiledSelect(false)}) AS sub"); + $builder->select('ot, fechaEncuadernado'); + $builder->where('cantidad > unidades_enviadas'); + + return $builder; + } + public static function findForNewEnvio() { diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php index 27eecf8c..c90fe1e5 100644 --- a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php @@ -130,7 +130,7 @@
- +
-
- - +
-
-
-

- -

+
+

+ +

+
+
+ + + + + + + + + + +
+ +
+ +
-
-
-
-

-
-
-
- -
- finalizado == 0 && $envioEntity->tipo_envio == 'estandar'): ?> -
-
- -
- -
-
- -
-
- -
- -
-
- - -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
-
- - -
-
-
- - -
-
- -
- -
+
-
+ -
- -
-

- -

- -
-
- - -
- -
-
-

- +

-
-
- - finalizado == 0) ? '' : 'readonly' ?> - value="codigo_seguimiento)) ?>"> -
-
- - finalizado == 0): ?> - - - - -
- finalizado == 0): ?> -
- +
+
+
+

- tipo_envio == 'estandar'): ?> -
-
- - + finalizado == 0 && $envioEntity->tipo_envio == 'estandar'): ?> +
+ +
+ +
+ +
+
+ +
+
+ +
+ +
+
+ + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+ + +
+
+
+ + +
+
+ +
+ + + +
+
+
-
+
+ +
+

+ +

+ +
+
+ + +
+ +
+
+
+ +
+
+

+ +

+ +
+
+ + finalizado == 0) ? '' : 'readonly' ?> + value="codigo_seguimiento)) ?>"> +
+
+ + finalizado == 0): ?> + + + + +
+ finalizado == 0): ?> +
+ +
+ tipo_envio == 'estandar'): ?> +
+ +
+ + +
+
+
+ +
- - endSection() ?> + endSection() ?> - section('css') ?> - - - - "> - " /> + section('css') ?> + + + + "> + " /> - endSection() ?> + endSection() ?> - section('additionalExternalJs') ?> - - - - - endSection() ?> \ No newline at end of file + section('additionalExternalJs') ?> + + + + + endSection() ?> \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js b/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js index 63c6c3e3..71c300f9 100644 --- a/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js +++ b/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js @@ -20,6 +20,7 @@ class EnvioEdit { ]; this.table = null; + this.tableProximosEnvios = null; this.buscarPedidos = new ClassSelect($("#buscadorPedidos"), '/logistica/selectAddLinea', "", true, { 'envio': $("#id").val() }); @@ -43,12 +44,6 @@ class EnvioEdit { this.proveedor.init(); } - if ($("#proximosEnvios").length) { - new PerfectScrollbar(document.getElementById('proximosEnvios'), { - wheelPropagation: false - }); - } - this.table = $('#tableLineasEnvio').DataTable({ processing: true, serverSide: true, @@ -101,6 +96,46 @@ class EnvioEdit { ] }); + this.tableProximosEnvios = $('#tableProximosEnvios').DataTable({ + processing: true, + serverSide: true, + autoWidth: true, + responsive: true, + scrollX: true, + orderCellsTop: true, + orderable: false, + order: [[1, 'asc']], + lengthMenu: [5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500], + pageLength: 5, + "dom": 'tp', + "ajax": { + "url": "/logistica/datatableProximosEnvios/" + $('#id').val(), + }, + "columns": [ + {data: 'ot'}, + {data: 'fechaEncuadernado'} + ], + "language": { + url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" + }, + "columnDefs": [ + { + "targets": [0, 1], + "className": "text-center", + }, + ], + drawCallback: function(){ + $(this.api().table().container()).find('table').css('width', '100%'); + this.api().columns.adjust(); + } + }); + + $('#proximosEnviosTip' + this.id).on('shown.bs.collapse', () => { + if (this.tableProximosEnvios) { + this.tableProximosEnvios.columns.adjust().draw(false); + } + }); + $('#btnImprimirEtiquetas').on('click', () => { const table = this.table; const selectedRows = table.rows({ page: 'current' }).nodes().filter((node) => { From 2ef98a949687a5aedfdaff84de1b1c9020b09b9c Mon Sep 17 00:00:00 2001 From: amazuecos Date: Mon, 19 May 2025 20:47:19 +0200 Subject: [PATCH 074/127] fix pdf font sizes and updated info --- .../vuexy/pdfs/encuadernados/default.php | 8 +- ci4/app/Views/themes/vuexy/pdfs/ferro.php | 101 +++++++++------ .../Views/themes/vuexy/pdfs/orden_trabajo.php | 122 ++++++++++-------- ci4/app/Views/themes/vuexy/pdfs/prototipo.php | 122 ++++++++++-------- .../assets/js/safekat/pages/pdf/otDownload.js | 23 ++-- httpdocs/themes/vuexy/css/pdf.ot.css | 47 ++++--- 6 files changed, 241 insertions(+), 182 deletions(-) diff --git a/ci4/app/Views/themes/vuexy/pdfs/encuadernados/default.php b/ci4/app/Views/themes/vuexy/pdfs/encuadernados/default.php index 07b92483..4ceaabee 100644 --- a/ci4/app/Views/themes/vuexy/pdfs/encuadernados/default.php +++ b/ci4/app/Views/themes/vuexy/pdfs/encuadernados/default.php @@ -1,9 +1,7 @@ - - - + @@ -12,9 +10,7 @@ 0): ?> - - - + diff --git a/ci4/app/Views/themes/vuexy/pdfs/ferro.php b/ci4/app/Views/themes/vuexy/pdfs/ferro.php index c59bdf65..0b95135d 100755 --- a/ci4/app/Views/themes/vuexy/pdfs/ferro.php +++ b/ci4/app/Views/themes/vuexy/pdfs/ferro.php @@ -56,13 +56,13 @@ $settings = $session->get('settings');
;color:;"> - fecha_encuadernado ? week_day_humanize(Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->getDayOfWeek() - 1, true) : "" ?> - Comercial: first_name . " " . $cliente->comercial()->last_name ?> + fecha_encuadernado ? week_day_humanize(Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->getDayOfWeek() - 1, true) : "" ?> + Comercial: first_name . " " . $cliente->comercial()->last_name ?>
- ;color:;"> + ;color:;"> POD presupuestoLineaImpresion()->isRotativa()): ?> @@ -70,18 +70,19 @@ $settings = $session->get('settings'); GENERAL - -
-
- +
+
+ ;">fecha_encuadernado ? Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->format('d/m/Y') : "" ?> +
+
-
EncuadernacionSobrecubierta Guardas Retractilado
tarifa()->nombre ?>hasSobrecubierta() ? "SI" : "NO" ?> guardas ? "SI" : "NO" ?> retractilado ? "SI" : "NO" ?>
+
@@ -103,26 +104,27 @@ $settings = $session->get('settings');
IN
+ -
+
-
;color:;"> - +
;color:;"> +
-
;color:;"> +
;color:;"> papel_impresion()->papel_code_ot ?>
-
"> +
">
-
;color:;"> +
;color:;"> papel_impresion()->papel_code_ot ?>
-
;color:;"> +
;color:;"> tarifa()->code : "" ?>
$acabado): ?> @@ -137,7 +139,7 @@ $settings = $session->get('settings');
">
- ;">id ?> + ;">id ?>
barcode @@ -151,32 +153,30 @@ $settings = $session->get('settings');
- +
- - + + - + - + - + - +
IDSK - - IDSK
CLIENTECLIENTE alias ?>
TITULOTITULO titulo ?>
ISBNISBN isbn ?>
PEDIDO CLIENTEPEDIDO id ?>
@@ -184,12 +184,10 @@ $settings = $session->get('settings');
- imposicion_esquema()): ?> imposicion_esquema()->svg_schema ?> -
@@ -204,21 +202,33 @@ $settings = $session->get('settings');
-
IMP. INTERIOR
+
+
IMP. INTERIOR
+ fecha_impresion): ?> +
fecha_impresion)->format('d/m/Y') ?>
+ +
- - - - - - - - - - - -
ancho ?>xalto ?> 1 tipo_presupuesto()?->codigo ?? "" ?> lomo_cubierta, 2, ',', '.') ?>
+ + + + + + + + + papel_formato_personalizado): ?> + + + + + + + + + +
papel_formato_ancho ?>xpapel_formato_alto ?> ancho ?>xalto ?> 1 tipo_presupuesto()?->codigo ?? "" ?> lomo_cubierta, 2, ',', '.') ?>
@@ -251,7 +261,7 @@ $settings = $session->get('settings');
-
+
Comentarios impresión interior

@@ -262,7 +272,12 @@ $settings = $session->get('settings');

-
LOGISTICA
+
+
LOGISTICA
+ fecha_entrega_real): ?> +
fecha_entrega_real)->format('d/m/Y') ?>
+ +
@@ -276,7 +291,7 @@ $settings = $session->get('settings');
-
-
+
Comentarios logistica:

diff --git a/ci4/app/Views/themes/vuexy/pdfs/orden_trabajo.php b/ci4/app/Views/themes/vuexy/pdfs/orden_trabajo.php index 62271989..065f73b5 100755 --- a/ci4/app/Views/themes/vuexy/pdfs/orden_trabajo.php +++ b/ci4/app/Views/themes/vuexy/pdfs/orden_trabajo.php @@ -48,21 +48,19 @@ $settings = $session->get('settings'); full_path)) : '/assets/img/portada_not_found.png' ?>" /> - -

;color:;">
;color:;"> - fecha_encuadernado ? week_day_humanize(Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->getDayOfWeek() - 1, true) : "" ?> - Comercial: first_name . " " . $cliente->comercial()->last_name ?> + fecha_encuadernado ? week_day_humanize(Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->getDayOfWeek() - 1, true) : "" ?> + Comercial: first_name . " " . $cliente->comercial()->last_name ?>
- ;color:;"> + ;color:;"> POD presupuestoLineaImpresion()->isRotativa()): ?> @@ -80,12 +78,12 @@ $settings = $session->get('settings');
-
- ;">fecha_encuadernado ? Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->format('d/m/Y') : "" ?> +
+ ;">fecha_encuadernado ? Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->format('d/m/Y') : "" ?>
- +
@@ -110,23 +108,23 @@ $settings = $session->get('settings'); -
+
-
;color:;"> - +
;color:;"> +
-
-
;color:;"> +
+
;color:;"> papel_impresion()->papel_code_ot ?>
-
"> +
">
-
;color:;"> +
;color:;"> papel_impresion()->papel_code_ot ?>
-
;color:;"> +
;color:;"> tarifa()->code : "" ?>
$acabado): ?> @@ -141,7 +139,7 @@ $settings = $session->get('settings');
">
- ;">id ?> + ;">id ?>
barcode @@ -155,32 +153,32 @@ $settings = $session->get('settings');
-
IN
+
- - + - + - + - + - +
IDSK + IDSK
CLIENTECLIENTE alias ?>
TITULOTITULO titulo ?>
ISBNISBN isbn ?>
PEDIDO CLIENTEPEDIDO id ?>
@@ -188,7 +186,6 @@ $settings = $session->get('settings');
- imposicion_esquema()): ?> imposicion_esquema()->svg_schema ?> @@ -208,19 +205,31 @@ $settings = $session->get('settings');
-
IMP. INTERIOR
+
+
IMP. INTERIOR
+ fecha_impresion): ?> +
fecha_impresion)->format('d/m/Y') ?>
+ +
- +
- - - + + + + + + + papel_formato_personalizado): ?> + + + + - - +
ancho ?>xalto ?>
papel_formato_ancho ?>xpapel_formato_alto ?> ancho ?>xalto ?> tirada ?> + merma ?> tipo_presupuesto()?->codigo ?? "" ?> lomo_cubierta, 2, ',', '.') ?>
@@ -235,12 +244,12 @@ $settings = $session->get('settings'); - - + + - + @@ -255,8 +264,8 @@ $settings = $session->get('settings');
Tiempo
paginas ?> tirada ?> paginas, 0, ',', '.') ?> tirada, 0, ',', '.') ?> tinta() ?> formas)->formas ?> maquina()->nombre ?>rotativa_clicks_total ?>rotativa_clicks_total, 0, ',', '.') ?> horas_maquina * 3600) ?>
-
-
+
+

comment_interior ?> @@ -270,7 +279,7 @@ $settings = $session->get('settings');

IMP. CUBIERTA
- +
@@ -294,7 +303,7 @@ $settings = $session->get('settings');
Tintas
-
+
@@ -308,12 +317,19 @@ $settings = $session->get('settings');
-
ACABADOS/ENCUADERNACIÓN
+
+
ACABADOS/ENCUADERNACIÓN
+ fecha_encuadernado): ?> +
fecha_encuadernado)->format('d/m/Y') ?>
+ +
-
;color:;"> - +
+
;color:;"> + +
- +
$acabado): ?> @@ -324,7 +340,7 @@ $settings = $session->get('settings'); - + @@ -345,14 +361,15 @@ $settings = $session->get('settings'); } } catch (\Throwable $th) { $error_message = $th->getMessage(); - echo "No se ha podido renderizar la tabla de encuadernación"; + // echo view("/themes/vuexy/pdfs/encuadernados/default.php", ["encuadernacion" => $encuadernacion]); + // echo "No se ha podido renderizar la tabla de encuadernación"; // echo "
$error_message"; } } ?> 0): ?> -
+

@@ -366,23 +383,26 @@ $settings = $session->get('settings');

-
LOGISTICA
+
+
LOGISTICA
+ fecha_entrega_real): ?> +
fecha_entrega_real)->format('d/m/Y') ?>
+ +
-
Plastificadoproveedor() ? $acabado->proveedor()->nombre : "" ?>
info_solapa_guillotina?>info_solapa_guillotina ?> CORTE PIE:
+
- -
Peso Unidad Peso Pedido CajasCorte Pie
gr 1000 ? number_format($peso_pedido / 1000, 2, ',', '.') . " kg" : number_format($peso_pedido, 2, ',', '.') . " gr" ?> --
-
+
diff --git a/ci4/app/Views/themes/vuexy/pdfs/prototipo.php b/ci4/app/Views/themes/vuexy/pdfs/prototipo.php index 29dd77b7..edcc540d 100755 --- a/ci4/app/Views/themes/vuexy/pdfs/prototipo.php +++ b/ci4/app/Views/themes/vuexy/pdfs/prototipo.php @@ -56,13 +56,13 @@ $settings = $session->get('settings');
;color:;"> - fecha_encuadernado ? week_day_humanize(Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->getDayOfWeek() - 1, true) : "" ?> - Comercial: first_name . " " . $cliente->comercial()->last_name ?> + fecha_encuadernado ? week_day_humanize(Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->getDayOfWeek() - 1, true) : "" ?> + Comercial: first_name . " " . $cliente->comercial()->last_name ?>
- ;color:;"> + ;color:;"> POD presupuestoLineaImpresion()->isRotativa()): ?> @@ -70,22 +70,19 @@ $settings = $session->get('settings'); GENERAL - -
-
-
- ;">fecha_encuadernado ? Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->format('d/m/Y') : "" ?> +
+ ;">fecha_encuadernado ? Time::createFromFormat("Y-m-d H:i:s", $pedido->fecha_encuadernado)->format('d/m/Y') : "" ?>
- +
@@ -107,26 +104,27 @@ $settings = $session->get('settings');
IN
+
-
+
-
;color:;"> - +
;color:;"> +
-
;color:;"> +
;color:;"> papel_impresion()->papel_code_ot ?>
-
"> +
">
-
;color:;"> +
;color:;"> papel_impresion()->papel_code_ot ?>
-
;color:;"> +
;color:;"> tarifa()->code : "" ?>
$acabado): ?> @@ -141,7 +139,7 @@ $settings = $session->get('settings');
">
- ;">id ?> + ;">id ?>
barcode @@ -155,32 +153,30 @@ $settings = $session->get('settings');
- +
- - + + - + - + - + - +
IDSK - - IDSK
CLIENTECLIENTE alias ?>
TITULOTITULO titulo ?>
ISBNISBN isbn ?>
PEDIDO CLIENTEPEDIDO id ?>
@@ -188,12 +184,10 @@ $settings = $session->get('settings');
- imposicion_esquema()): ?> imposicion_esquema()->svg_schema ?> -
@@ -208,19 +202,31 @@ $settings = $session->get('settings');
-
IMP. INTERIOR
+
+
IMP. INTERIOR
+ fecha_impresion): ?> +
fecha_impresion)->format('d/m/Y') ?>
+ +
- +
- - - - - + + + + + + + papel_formato_personalizado): ?> + + + + + - +
ancho ?>xalto ?> tirada/$presupuesto->tirada ?>
papel_formato_ancho ?>xpapel_formato_alto ?> ancho ?>xalto ?> 1 tipo_presupuesto()?->codigo ?? "" ?> lomo_cubierta, 2, ',', '.') ?>
@@ -236,7 +242,7 @@ $settings = $session->get('settings'); - + @@ -255,8 +261,8 @@ $settings = $session->get('settings');
paginas ?> tirada / $presupuesto->tirada ?> 1 tinta() ?> formas)->formas ?> maquina()->nombre ?>
-
-
+
+
Comentarios impresión interior

comment_interior ?> @@ -281,10 +287,10 @@ $settings = $session->get('settings'); tinta() ?> - tirada/$presupuesto->tirada ?> + tirada / $presupuesto->tirada ?> maquina()->nombre ?> marcapaginas ? "SI" : "NO" ?> - horas_maquina * 3600/$presupuesto->tirada) ?> + horas_maquina * 3600 / $presupuesto->tirada) ?> formas)->maquina_ancho ?>xformas)->maquina_alto ?> @@ -294,7 +300,7 @@ $settings = $session->get('settings'); -

+
@@ -308,10 +314,17 @@ $settings = $session->get('settings');
-
ACABADOS/ENCUADERNACIÓN
+
+
ACABADOS/ENCUADERNACIÓN
+ fecha_encuadernado): ?> +
fecha_encuadernado)->format('d/m/Y') ?>
+ +
-
;color:;"> - +
+
;color:;"> + +
$acabado): ?> @@ -324,7 +337,7 @@ $settings = $session->get('settings'); - + @@ -345,14 +358,15 @@ $settings = $session->get('settings'); } } catch (\Throwable $th) { $error_message = $th->getMessage(); - echo "No se ha podido renderizar la tabla de encuadernación"; + // echo view("/themes/vuexy/pdfs/encuadernados/default.php", ["encuadernacion" => $encuadernacion]); + // echo "No se ha podido renderizar la tabla de encuadernación"; // echo "
$error_message"; } } ?> 0): ?> -
+

@@ -366,7 +380,12 @@ $settings = $session->get('settings');

-
LOGISTICA
+
+
LOGISTICA
+ fecha_entrega_real): ?> +
fecha_entrega_real)->format('d/m/Y') ?>
+ +
proveedor() ? $acabado->proveedor()->nombre : "" ?>
info_solapa_guillotina?>info_solapa_guillotina ?> CORTE PIE:
@@ -380,9 +399,8 @@ $settings = $session->get('settings');
-
-
-
- +
+
Comentarios logistica:

comment_logistica ?> diff --git a/httpdocs/assets/js/safekat/pages/pdf/otDownload.js b/httpdocs/assets/js/safekat/pages/pdf/otDownload.js index da577046..08335c94 100644 --- a/httpdocs/assets/js/safekat/pages/pdf/otDownload.js +++ b/httpdocs/assets/js/safekat/pages/pdf/otDownload.js @@ -1,11 +1,12 @@ -$(() => { - var opt = { - margin: 2, - filename: $(".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() -}) \ No newline at end of file +// $(() => { +// var opt = { +// margin: 2, +// filename: $(".pdf-wrapper").data("id") + ".pdf", +// image: { type: 'jpeg', quality: 1 }, +// html2canvas: { scale: 4 }, +// jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }, +// pagebreak: { mode: ['avoid-all', 'css', 'legacy'] } +// }; +// let elementToPdf = $('body')[0] +// html2pdf().set(opt).from(elementToPdf).save() +// }) \ No newline at end of file diff --git a/httpdocs/themes/vuexy/css/pdf.ot.css b/httpdocs/themes/vuexy/css/pdf.ot.css index 3058c604..e773c58e 100644 --- a/httpdocs/themes/vuexy/css/pdf.ot.css +++ b/httpdocs/themes/vuexy/css/pdf.ot.css @@ -3,22 +3,23 @@ margin: 0; } @media print { - .page, - { + .page { width: 210mm; height: 297mm; max-width: 210mm; max-height: 297mm; print-color-adjust: exact; } + /* ... the rest of the rules ... */ } -html { +html,body { font-family: Arial, sans-serif; width: 210mm; height: 297mm; max-width: 210mm; - font-size: 8px; + width: 100%; + font-size: 14px; max-height: 297mm; background-color: white; } @@ -26,7 +27,8 @@ html { .page { border: 0px solid; padding: 10px; - margin : 10px; + margin: 10px; + width: 100%; max-width: 210mm; max-height: 297mm; background-color: white; @@ -37,11 +39,11 @@ html { border: 2px solid; } .square { + height : 75px; align-items: center; align-content: center; justify-content: center; font-weight: bold; - font-size: 14px; } .esquema { } @@ -92,6 +94,7 @@ html { } .section-title { font-weight: bold; + font-size: 1.2em; margin-bottom: 4px; } .cubierta { @@ -106,37 +109,39 @@ html { .comments { color: #555; font-style: italic; - font-size : 12px; + font-size: 12px; margin-top: 0.2rem; } .comment-content { width: 100%; - margin-left : 0.2rem; + margin-left: 0.2rem; font-style: normal; - color : black; + color: black; font-size: 10px; } table { width: 100%; margin-bottom: 2px; - font-size: 10px; + font-size: 1.2em; } -th, td { - border: 0.01px solid black; + +th, +td { + border-width : 1px; + border-color : black; } table td { text-align: center; } - table th { font-weight: bold; color: black; text-align: center; } -table td { - font-weight: bold; +.al{ + text-align:left; } .t-header { @@ -149,7 +154,7 @@ table td { padding-left: 0.2rem; } .t-row { - font-size: 8px; + font-size: 14px; width: 100%; } .bicolor { @@ -173,9 +178,7 @@ table td { background: black; color: white; } -.footer { - font-size: 10px; -} + .bg-encuadernacion { background-color: #bbd8a3; } @@ -185,3 +188,9 @@ table td { .cell-50 { width: 50px; } +.ot-code { + font-size: 4em; +} +.code-title { + font-size: 1.5em; +} From 64337257eed355f21d6398443fbdc2ea62694f33 Mon Sep 17 00:00:00 2001 From: amazuecos Date: Mon, 19 May 2025 20:57:40 +0200 Subject: [PATCH 075/127] add alias_ot field to lg_maquinas --- ...9-204800_AddAliasOtColumnMaquinasTable.php | 26 ++ ci4/app/Entities/Configuracion/Maquina.php | 4 +- ci4/app/Language/en/Maquinas.php | 1 + ci4/app/Language/es/Maquinas.php | 270 +++++++++--------- ci4/app/Models/Configuracion/MaquinaModel.php | 8 + .../maquinas/_maquinaFormItems.php | 7 + 6 files changed, 182 insertions(+), 134 deletions(-) create mode 100644 ci4/app/Database/Migrations/2025-05-19-204800_AddAliasOtColumnMaquinasTable.php diff --git a/ci4/app/Database/Migrations/2025-05-19-204800_AddAliasOtColumnMaquinasTable.php b/ci4/app/Database/Migrations/2025-05-19-204800_AddAliasOtColumnMaquinasTable.php new file mode 100644 index 00000000..0d5f03ca --- /dev/null +++ b/ci4/app/Database/Migrations/2025-05-19-204800_AddAliasOtColumnMaquinasTable.php @@ -0,0 +1,26 @@ + [ + "type" => "VARCHAR", + "constraint" => 255, + "null" => true + ], + ]; + public function up() + { + $this->forge->addColumn('lg_maquinas', $this->COLUMNS); + } + + public function down() + { + $this->forge->dropColumn('lg_maquinas', array_keys($this->COLUMNS)); + } +} diff --git a/ci4/app/Entities/Configuracion/Maquina.php b/ci4/app/Entities/Configuracion/Maquina.php index 6b9f6cf8..1d8fbc8e 100755 --- a/ci4/app/Entities/Configuracion/Maquina.php +++ b/ci4/app/Entities/Configuracion/Maquina.php @@ -42,7 +42,8 @@ class Maquina extends \CodeIgniter\Entity\Entity "updated_at" => null, "user_created_id" => 0, "user_updated_id" => 0, - "etiqueta_envio" => false + "etiqueta_envio" => false, + "alias_ot" => null, ]; protected $casts = [ "is_padre" => "boolean", @@ -70,6 +71,7 @@ class Maquina extends \CodeIgniter\Entity\Entity "is_deleted" => "int", "user_created_id" => "int", "user_updated_id" => "int", + "alias_ot" => "?string" ]; public function papeles_impresion() : ?array diff --git a/ci4/app/Language/en/Maquinas.php b/ci4/app/Language/en/Maquinas.php index 96f5ee61..2d87ba4a 100755 --- a/ci4/app/Language/en/Maquinas.php +++ b/ci4/app/Language/en/Maquinas.php @@ -29,6 +29,7 @@ return [ 'min' => 'Min POD', 'moduleTitle' => 'Machines', 'nombre' => 'Name', + 'alias_ot' => 'Alias', 'observaciones' => 'Remarks', 'ordenPlanning' => 'Planning order', 'padreId' => 'Variante', diff --git a/ci4/app/Language/es/Maquinas.php b/ci4/app/Language/es/Maquinas.php index a8ea07b9..b09ab7ce 100755 --- a/ci4/app/Language/es/Maquinas.php +++ b/ci4/app/Language/es/Maquinas.php @@ -3,175 +3,179 @@ return [ - 'acabado' => 'acabado', - 'alto' => 'Alto', - 'altoClick' => 'Alto Click', - 'altoImpresion' => 'Alto Impresion', - 'ancho' => 'Ancho', - 'anchoImpresion' => 'Ancho Impresion', - 'createdAt' => 'Created At', - 'deletedAt' => 'Deleted At', - 'duracionJornada' => 'Duracion Jornada', - 'forzarNumFormasHorizontalesPortada' => 'Forzar Num Formas Horizontales Cubierta', - 'forzarNumFormasVerticalesPortada' => 'Forzar Num Formas Verticales Cubierta', - 'id' => 'ID', - 'impresion' => 'impresion', - 'isDeleted' => 'Is Deleted', - 'isPadre' => 'Usar para variante?', - 'isRotativa' => 'Es Rotativa?', - 'isTinta' => 'Inkjet', - 'isEtiquetaEnvio' => 'Etiqueta títulos', - 'manipulado' => 'manipulado', - 'maquina' => 'Maquina', - 'maquinaList' => 'Lista Máquinas', - 'maquinas' => 'Máquinas', - 'max' => 'POD Max', - 'metrosxminuto' => 'Metros x minuto', - 'min' => 'POD Min', - 'moduleTitle' => 'Máquinas', - 'nombre' => 'Nombre', - 'observaciones' => 'Observaciones', - 'ordenPlanning' => 'Orden Planning', - 'padreId' => 'Variante', - 'precioHoraCorte' => 'Precio Hora Corte', - 'precioTintaCG' => 'Precio Tinta CG', - 'precioTintaColor' => 'Precio Tinta Color', - 'precioTintaNegro' => 'Precio Tinta Negro', - 'tipo' => 'Tipo', - 'updatedAt' => 'Updated At', - 'userCreatedId' => 'User Created ID', - 'userUpdatedId' => 'User Updated ID', - 'velocidad' => 'Velocidad', - 'velocidadCorte' => 'Velocidad Corte', - 'maquina_tarea' => 'Máquina tarea', - 'namePlaceholderDuplicated' => "Inserte el nombre de la máquina a duplicar ...", - 'validation' => [ - 'alto_menor_alto_impresion' => 'El campo \'Alto impresión\' debe ser menor que \'Alto\'', - 'ancho_menor_ancho_impresion' => '\'Ancho Impresión\' debe ser menor que \'Ancho\'', - 'alto' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'greater_than' => 'El campo {field} debe ser mayor que {param}', - ], + 'acabado' => 'acabado', + 'alto' => 'Alto', + 'altoClick' => 'Alto Click', + 'altoImpresion' => 'Alto Impresion', + 'ancho' => 'Ancho', + 'anchoImpresion' => 'Ancho Impresion', + 'createdAt' => 'Created At', + 'deletedAt' => 'Deleted At', + 'duracionJornada' => 'Duracion Jornada', + 'forzarNumFormasHorizontalesPortada' => 'Forzar Num Formas Horizontales Cubierta', + 'forzarNumFormasVerticalesPortada' => 'Forzar Num Formas Verticales Cubierta', + 'id' => 'ID', + 'impresion' => 'impresion', + 'isDeleted' => 'Is Deleted', + 'isPadre' => 'Usar para variante?', + 'isRotativa' => 'Es Rotativa?', + 'isTinta' => 'Inkjet', + 'isEtiquetaEnvio' => 'Etiqueta títulos', + 'manipulado' => 'manipulado', + 'maquina' => 'Maquina', + 'maquinaList' => 'Lista Máquinas', + 'maquinas' => 'Máquinas', + 'max' => 'POD Max', + 'metrosxminuto' => 'Metros x minuto', + 'min' => 'POD Min', + 'moduleTitle' => 'Máquinas', + 'nombre' => 'Nombre', + 'alias_ot' => 'Alias', + 'observaciones' => 'Observaciones', + 'ordenPlanning' => 'Orden Planning', + 'padreId' => 'Variante', + 'precioHoraCorte' => 'Precio Hora Corte', + 'precioTintaCG' => 'Precio Tinta CG', + 'precioTintaColor' => 'Precio Tinta Color', + 'precioTintaNegro' => 'Precio Tinta Negro', + 'tipo' => 'Tipo', + 'updatedAt' => 'Updated At', + 'userCreatedId' => 'User Created ID', + 'userUpdatedId' => 'User Updated ID', + 'velocidad' => 'Velocidad', + 'velocidadCorte' => 'Velocidad Corte', + 'maquina_tarea' => 'Máquina tarea', + 'namePlaceholderDuplicated' => "Inserte el nombre de la máquina a duplicar ...", + 'validation' => [ + 'alto_menor_alto_impresion' => 'El campo \'Alto impresión\' debe ser menor que \'Alto\'', + 'ancho_menor_ancho_impresion' => '\'Ancho Impresión\' debe ser menor que \'Ancho\'', + 'alto' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'greater_than' => 'El campo {field} debe ser mayor que {param}', + ], - 'ancho' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'greater_than' => 'El campo {field} debe ser mayor que {param}', - ], + 'ancho' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'greater_than' => 'El campo {field} debe ser mayor que {param}', + ], - 'forzar_num_formas_horizontales_cubierta' => [ - 'integer' => 'El campo {field} debe contener un número entero.', + 'forzar_num_formas_horizontales_cubierta' => [ + 'integer' => 'El campo {field} debe contener un número entero.', - ], + ], - 'forzar_num_formas_verticales_cubierta' => [ - 'integer' => 'El campo {field} debe contener un número entero.', + 'forzar_num_formas_verticales_cubierta' => [ + 'integer' => 'El campo {field} debe contener un número entero.', - ], + ], - 'alto_click' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', - 'greater_than' => 'El campo {field} debe ser mayor que {param}', - ], + 'alto_click' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', + 'greater_than' => 'El campo {field} debe ser mayor que {param}', + ], - 'alto_impresion' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', - 'greater_than' => 'El campo {field} debe ser mayor que {param}', - ], + 'alto_impresion' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', + 'greater_than' => 'El campo {field} debe ser mayor que {param}', + ], - 'ancho_impresion' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', - 'greater_than' => 'El campo {field} debe ser mayor que {param}', - ], + 'ancho_impresion' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', + 'greater_than' => 'El campo {field} debe ser mayor que {param}', + ], - 'duracion_jornada' => [ - 'integer' => 'El campo {field} debe contener un número entero.', - 'required' => 'El campo {field} es obligatorio.', + 'duracion_jornada' => [ + 'integer' => 'El campo {field} debe contener un número entero.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'max' => [ - 'integer' => 'El campo {field} debe contener un número entero.', - 'required' => 'El campo {field} es obligatorio.', + 'max' => [ + 'integer' => 'El campo {field} debe contener un número entero.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'metrosxminuto' => [ - 'max_length' => 'El campo {field} no puede exeder de {param} caracteres de longitud.', - 'required' => 'El campo {field} es obligatorio.', + 'metrosxminuto' => [ + 'max_length' => 'El campo {field} no puede exceder de {param} caracteres de longitud.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'min' => [ - 'integer' => 'El campo {field} debe contener un número entero.', - 'required' => 'El campo {field} es obligatorio.', + 'min' => [ + 'integer' => 'El campo {field} debe contener un número entero.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'nombre' => [ - 'max_length' => 'El campo {field} no puede exeder de {param} caracteres de longitud.', - 'required' => 'El campo {field} es obligatorio.', + 'nombre' => [ + 'max_length' => 'El campo {field} no puede exceder de {param} caracteres de longitud.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], + 'alias' => [ + 'max_length' => 'El campo {field} no puede exceder de {param} caracteres de longitud.', + ], - 'observaciones' => [ - 'max_length' => 'El campo {field} no puede exeder de {param} caracteres de longitud.', - 'required' => 'El campo {field} es obligatorio.', + 'observaciones' => [ + 'max_length' => 'El campo {field} no puede exceder de {param} caracteres de longitud.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'orden_planning' => [ - 'integer' => 'El campo {field} debe contener un número entero.', - 'required' => 'El campo {field} es obligatorio.', + 'orden_planning' => [ + 'integer' => 'El campo {field} debe contener un número entero.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'precio_hora_corte' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', + 'precio_hora_corte' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'precio_tinta_cg' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', + 'precio_tinta_cg' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'precio_tinta_color' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', + 'precio_tinta_color' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'precio_tinta_negro' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', + 'precio_tinta_negro' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'tipo' => [ - 'in_list' => 'El campo {field} debe ser uno uno de: {param}.', - 'required' => 'El campo {field} es obligatorio.', + 'tipo' => [ + 'in_list' => 'El campo {field} debe ser uno uno de: {param}.', + 'required' => 'El campo {field} es obligatorio.', - ], + ], - 'velocidad' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', + 'velocidad' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', - ], - - 'velocidad_corte' => [ - 'decimal' => 'El campo {field} debe contener un número decimal.', - 'required' => 'El campo {field} es obligatorio.', - - ], + ], + 'velocidad_corte' => [ + 'decimal' => 'El campo {field} debe contener un número decimal.', + 'required' => 'El campo {field} es obligatorio.', ], -]; \ No newline at end of file + ], + + +]; diff --git a/ci4/app/Models/Configuracion/MaquinaModel.php b/ci4/app/Models/Configuracion/MaquinaModel.php index 74e96cb7..616a5b1b 100755 --- a/ci4/app/Models/Configuracion/MaquinaModel.php +++ b/ci4/app/Models/Configuracion/MaquinaModel.php @@ -54,6 +54,7 @@ class MaquinaModel extends \App\Models\BaseModel "user_created_id", "user_updated_id", "etiqueta_envio", + "alias_ot", ]; protected $returnType = "App\Entities\Configuracion\Maquina"; @@ -149,6 +150,10 @@ class MaquinaModel extends \App\Models\BaseModel "label" => "Maquinas.velocidadCorte", "rules" => "decimal", ], + "alias_ot" => [ + "label" => "Maquinas.alias_ot", + "rules" => "trim|max_length[255]", + ], ]; protected $validationMessages = [ @@ -196,6 +201,9 @@ class MaquinaModel extends \App\Models\BaseModel "max_length" => "Maquinas.validation.nombre.max_length", "required" => "Maquinas.validation.nombre.required", ], + "alias_ot" => [ + "max_length" => "Maquinas.validation.alias.max_length" + ], "observaciones" => [ "max_length" => "Maquinas.validation.observaciones.max_length", //"required" => "Maquinas.validation.observaciones.required", diff --git a/ci4/app/Views/themes/vuexy/form/configuracion/maquinas/_maquinaFormItems.php b/ci4/app/Views/themes/vuexy/form/configuracion/maquinas/_maquinaFormItems.php index 2b64ba70..cc027ddb 100755 --- a/ci4/app/Views/themes/vuexy/form/configuracion/maquinas/_maquinaFormItems.php +++ b/ci4/app/Views/themes/vuexy/form/configuracion/maquinas/_maquinaFormItems.php @@ -6,6 +6,13 @@ +

+
+ +
\ No newline at end of file diff --git a/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js b/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js index e06e5e25..17d99e2e 100644 --- a/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js +++ b/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js @@ -297,6 +297,10 @@ class Catalogo { this.initPedidosTable(); + $('#collapsePedidos').on('shown.bs.collapse', function () { + $('#tablaPedidosAntiguos').DataTable().columns.adjust().responsive.recalc(); + }); + // Al cargar la página this.toggleSobrecubiertaFields(); @@ -343,14 +347,7 @@ class Catalogo { lengthMenu: [5, 10, 25, 50, 75, 100], pageLength: 10, lengthChange: true, - dom: 'lfBrtip', - buttons: [ - 'copy', 'csv', 'excel', 'print', { - extend: 'pdfHtml5', - orientation: 'landscape', - pageSize: 'A4' - } - ], + dom: 'lfrtip', order: [[1, 'desc']], language: { url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" @@ -372,9 +369,8 @@ class Catalogo { columns: [ { data: 'id' }, { data: 'created_at' }, - { data: 'titulo' }, - { data: 'paginas' }, { data: 'tirada' }, + { data: 'precio_ud' , searchable: false, orderable: false }, { data: 'total' }, { data: 'estado' }, { data: 'actionBtns' } From 10889a9e7f705025e10c02438b49849f704a3e6b Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Thu, 5 Jun 2025 08:44:34 +0200 Subject: [PATCH 116/127] Refactorizazion --- ci4/app/Views/themes/vuexy/form/catalogo/_historicoPedidos.php | 2 +- httpdocs/assets/js/safekat/pages/catalogo/catalogo.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ci4/app/Views/themes/vuexy/form/catalogo/_historicoPedidos.php b/ci4/app/Views/themes/vuexy/form/catalogo/_historicoPedidos.php index 7fd66c69..a16221cc 100644 --- a/ci4/app/Views/themes/vuexy/form/catalogo/_historicoPedidos.php +++ b/ci4/app/Views/themes/vuexy/form/catalogo/_historicoPedidos.php @@ -35,7 +35,7 @@
Pedidos - Antiguo ERP
- +
diff --git a/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js b/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js index 17d99e2e..d082c455 100644 --- a/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js +++ b/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js @@ -297,6 +297,7 @@ class Catalogo { this.initPedidosTable(); + // Ajustar al ancho de contenendor la tabla de historizo de pedidos $('#collapsePedidos').on('shown.bs.collapse', function () { $('#tablaPedidosAntiguos').DataTable().columns.adjust().responsive.recalc(); }); From b1cd63f665a8a3af10e2bc96ae1a9360980901f9 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Thu, 5 Jun 2025 09:28:30 +0200 Subject: [PATCH 117/127] Arreglado precio ud en tabla --- ci4/app/Controllers/Catalogo/CatalogoLibros.php | 3 ++- httpdocs/assets/js/safekat/pages/catalogo/catalogo.js | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ci4/app/Controllers/Catalogo/CatalogoLibros.php b/ci4/app/Controllers/Catalogo/CatalogoLibros.php index b990feaa..1d451c6d 100644 --- a/ci4/app/Controllers/Catalogo/CatalogoLibros.php +++ b/ci4/app/Controllers/Catalogo/CatalogoLibros.php @@ -252,11 +252,12 @@ class CatalogoLibros extends BaseResourceController 't1.id', 't1.created_at', 't1.tirada', + '(CASE WHEN t1.tirada > 0 THEN t1.total / t1.tirada ELSE 0 END)', 't1.total', 't1.estado' ]) ->edit('total', fn($row) => number_format((float) $row->total, 2, ',', '.') . ' €') - ->edit('precio_ud', fn($row) => number_format((float) $row->total, 2, ',', '.') . ' €') + ->edit('precio_ud', fn($row) => number_format((float) $row->precio_ud, 2, ',', '.') . ' €') ->edit('created_at', fn($row) => date('d/m/Y', strtotime($row->created_at))) ->add('actionBtns', function ($row) { return '
diff --git a/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js b/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js index d082c455..38586991 100644 --- a/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js +++ b/httpdocs/assets/js/safekat/pages/catalogo/catalogo.js @@ -299,7 +299,11 @@ class Catalogo { // Ajustar al ancho de contenendor la tabla de historizo de pedidos $('#collapsePedidos').on('shown.bs.collapse', function () { - $('#tablaPedidosAntiguos').DataTable().columns.adjust().responsive.recalc(); + const table = $('#tablaPedidosAntiguos').DataTable(); + table.columns.adjust(); + if (typeof table.responsive !== 'undefined') { + table.responsive.recalc(); + } }); // Al cargar la página @@ -371,7 +375,7 @@ class Catalogo { { data: 'id' }, { data: 'created_at' }, { data: 'tirada' }, - { data: 'precio_ud' , searchable: false, orderable: false }, + { data: 'precio_ud' }, { data: 'total' }, { data: 'estado' }, { data: 'actionBtns' } From 602fb591f92ede4b8aca71cf1c41f8ca9a7a699c Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Thu, 5 Jun 2025 11:38:16 +0200 Subject: [PATCH 118/127] =?UTF-8?q?A=C3=B1adida=20funcionalidad=20de=20alb?= =?UTF-8?q?aran=20anonimo=20y=20corregidos=20bugs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci4/app/Config/Routes.php | 1 + ci4/app/Controllers/Pdf/PrintAlbaranes.php | 51 +++++++ ci4/app/Language/es/Albaran.php | 1 + .../themes/vuexy/pdfs/albaran-anonimo.php | 137 ++++++++++++++++++ .../js/safekat/components/albaranComponent.js | 12 +- 5 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 2b8b0b45..e6888b26 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -575,6 +575,7 @@ $routes->group( function ($routes) { $routes->get('index/(:num)', 'PrintAlbaranes::index/$1', ['as' => 'viewAlbaranPDF']); $routes->get('generar/(:num)', 'PrintAlbaranes::generar/$1', ['as' => 'albaranToPdf']); + $routes->get('generar-anonimo/(:num)', 'PrintAlbaranes::generarAnonimo/$1', ['as' => 'albaranAnonimoToPdf']); } ); diff --git a/ci4/app/Controllers/Pdf/PrintAlbaranes.php b/ci4/app/Controllers/Pdf/PrintAlbaranes.php index 4ebaeb73..56da19e5 100755 --- a/ci4/app/Controllers/Pdf/PrintAlbaranes.php +++ b/ci4/app/Controllers/Pdf/PrintAlbaranes.php @@ -71,4 +71,55 @@ class PrintAlbaranes extends BaseController ->setHeader('Content-Length', strlen($output)) ->setBody($output); } + + public function generarAnonimo($albaran_id) + { + + // Cargar modelos + $albaranModel = model('App\Models\Albaranes\AlbaranModel'); + $lineasAlbaranModel = model('App\Models\Albaranes\AlbaranLineaModel'); + + // Informacion del presupuesto + $data['albaran'] = $albaranModel->getResourceForPdf($albaran_id)->get()->getRow(); + $data['albaranLineas'] = $lineasAlbaranModel->getResourceForPdf($albaran_id)->get()->getResultObject(); + + + // Obtener contenido HTML de la vista + $html = view(getenv('theme.path') . 'pdfs/albaran-anonimo', $data); + + // Cargar CSS desde archivo local + $css = file_get_contents(FCPATH . 'themes/vuexy/css/pdf.albaran.css'); + // Combinar CSS y HTML + $html_con_css = "" . $html; + + // Crear una instancia de Dompdf + $options = new \Dompdf\Options(); + $options->set('isHtml5ParserEnabled', true); + $options->set('isPhpEnabled', true); + $options->set('isRemoteEnabled', true); + $dompdf = new \Dompdf\Dompdf($options); + + // Contenido HTML del documento + $dompdf->loadHtml($html_con_css); + + // Establecer el tamaño del papel + $dompdf->setPaper('A4', 'portrait'); + + // Renderizar el PDF + $dompdf->render(); + + // Obtener el contenido generado + $output = $dompdf->output(); + + // Establecer las cabeceras para visualizar en lugar de descargar + $file_name = "alabaran-$albaran_id.pdf"; + return $this->response + ->setStatusCode(200) + ->setHeader('Content-Type', 'application/pdf') + ->setHeader('Content-Disposition', 'inline; filename="' . $file_name . '"') + ->setHeader('Cache-Control', 'private, max-age=0, must-revalidate') + ->setHeader('Pragma', 'public') + ->setHeader('Content-Length', strlen($output)) + ->setBody($output); + } } \ No newline at end of file diff --git a/ci4/app/Language/es/Albaran.php b/ci4/app/Language/es/Albaran.php index fcfcb674..67dc8b37 100644 --- a/ci4/app/Language/es/Albaran.php +++ b/ci4/app/Language/es/Albaran.php @@ -28,6 +28,7 @@ return [ 'addIva' => 'Añadir IVA', 'nuevaLinea' => 'Nueva línea', 'imprimirAlbaran' => 'Imprimir albarán', + 'imprimirAlbaranAnonimo' => 'Imprimir albarán anónimo', 'borrarAlbaran' => 'Borrar albarán', 'borrarAlbaranConfirm' => '¿Está seguro de que desea borrar el albarán?', 'borrar' => 'Borrar', diff --git a/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php b/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php new file mode 100644 index 00000000..c7fc09eb --- /dev/null +++ b/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + +
+ mostrar_precios == 1; ?> + +
+ +
+ + + + + + + + + + + + + + + + + total; + ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Nº Unid.PedidoTítuloISBNRef. Cliente€/ud.Subtotal
+ unidades ?> + + pedido ?> + +
titulo ?>
+
+
isbn ?>
+
+
ref_cliente ?>
+
+ titulo, "IVA")): ?> +
precio_unidad, 4, ',', '.') ?>
+ +
+
total, 2, ',', '.') ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + +
+ RECIBÍ + + TOTAL + + +
+ + + + + \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/components/albaranComponent.js b/httpdocs/assets/js/safekat/components/albaranComponent.js index 12f1ac11..964a2053 100644 --- a/httpdocs/assets/js/safekat/components/albaranComponent.js +++ b/httpdocs/assets/js/safekat/components/albaranComponent.js @@ -192,6 +192,9 @@ class AlbaranComponent { + @@ -600,7 +603,14 @@ class AlbaranComponent { var albaran_id = this.id; window.open('/print-albaran/generar/'+ albaran_id , '_blank'); - }); + }); + + $('#imprimir_albaran_anonimo_' + this.id).on('click', (e) => { + + var albaran_id = this.id; + window.open('/print-albaran/generar-anonimo/'+ albaran_id , '_blank'); + + }); } _initAutoNumericInputs() { From 909228512cd22682dbd244313d2bfdee9b00ea1d Mon Sep 17 00:00:00 2001 From: Ignacio Martinez Navajas Date: Thu, 5 Jun 2025 11:45:00 +0200 Subject: [PATCH 119/127] Feedback JM --- .../themes/vuexy/pdfs/albaran-anonimo.php | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php b/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php index c7fc09eb..db93eda4 100644 --- a/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php +++ b/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php @@ -17,7 +17,7 @@ } .espaciado-superior { - margin-top: 80px; + margin-top: 40px; } @@ -29,6 +29,45 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Nº ALBARÁN: + + id ?> + + + + FECHA: + + fecha_albaran ? $albaran->fecha_albaran : date('d-m-Y') ?> +
Cliente: cliente ?>
Att: att ?>
direccion ?>
Cajas: cajas ?>
+ From 6a9331747e2bf23e16fc659f75c4197b95be5a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Thu, 5 Jun 2025 18:57:03 +0200 Subject: [PATCH 120/127] solucionado el problema de la impresion de las ots --- .../assets/js/safekat/pages/pdf/otDownload.js | 27 ++++++++++---- httpdocs/themes/vuexy/css/pdf.ot.css | 37 +++++++++++++++---- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/httpdocs/assets/js/safekat/pages/pdf/otDownload.js b/httpdocs/assets/js/safekat/pages/pdf/otDownload.js index c666e800..1652920a 100644 --- a/httpdocs/assets/js/safekat/pages/pdf/otDownload.js +++ b/httpdocs/assets/js/safekat/pages/pdf/otDownload.js @@ -1,11 +1,24 @@ $(() => { - var opt = { - margin: 2, + const elementToPdf = document.querySelector('body'); // o .pdf-wrapper si quieres acotar + + const opt = { + margin: 2, // un margen decente filename: $(".pdf-wrapper").data("id") + ".pdf", - image: { type: 'jpeg', quality: 1 }, - html2canvas: { scale: 4 }, + image: { type: 'jpeg', quality: 0.98 }, + html2canvas: { + scale: 4, + useCORS: true, + scrollY: -window.scrollY, // importante + //windowWidth: document.body.scrollWidth, + //windowHeight: document.body.scrollHeight + }, jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }, + pagebreak: { + mode: ['css', 'legacy'], // intenta usar los saltos naturales + before: '.page-break', // puedes insertar
si lo necesitas + avoid: ['table', 'tr', '.row'] // evita cortar tablas + } }; - let elementToPdf = $('body')[0] - html2pdf().set(opt).from(elementToPdf).save() -}) \ No newline at end of file + + html2pdf().set(opt).from(elementToPdf).toPdf().get('pdf').save(); +}); \ No newline at end of file diff --git a/httpdocs/themes/vuexy/css/pdf.ot.css b/httpdocs/themes/vuexy/css/pdf.ot.css index e773c58e..c0c29e2e 100644 --- a/httpdocs/themes/vuexy/css/pdf.ot.css +++ b/httpdocs/themes/vuexy/css/pdf.ot.css @@ -13,24 +13,38 @@ /* ... the rest of the rules ... */ } -html,body { - font-family: Arial, sans-serif; +html, body { width: 210mm; - height: 297mm; max-width: 210mm; - width: 100%; + margin: 0 auto; + padding: 0; + background: white; + font-family: Arial, sans-serif; font-size: 14px; - max-height: 297mm; - background-color: white; + box-sizing: border-box; + overflow-x: hidden; } +.pdf-wrapper { + width: 100%; + box-sizing: border-box; +} + +/* Opcional: ayuda a evitar cortes raros en tablas o secciones */ +.page-break { + page-break-before: always; +} + + .page { border: 0px solid; padding: 10px; margin: 10px; width: 100%; max-width: 210mm; - max-height: 297mm; + height: auto !important; + max-height: none !important; + /*max-height: 297mm;*/ background-color: white; } .portada-img { @@ -189,8 +203,15 @@ table th { width: 50px; } .ot-code { - font-size: 4em; + font-size: 3.5em; } .code-title { font-size: 1.5em; } + +body, html, .pdf-wrapper, .page, div { + box-sizing: border-box; + max-width: 210mm; + overflow-x: hidden; + word-wrap: break-word; +} \ No newline at end of file From 49140cea40c7990c217bf36000caeef23b7f4979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Thu, 5 Jun 2025 21:25:48 +0200 Subject: [PATCH 121/127] =?UTF-8?q?arreglado=20albaranes=20para=20que=20mu?= =?UTF-8?q?estren=20las=20cajas.=20tambien=20se=20ha=20actualizado=20para?= =?UTF-8?q?=20que=20cuando=20se=20modifiquen=20las=20cajas=20de=20la=20lin?= =?UTF-8?q?ea=20se=20modifiquen=20el=20total=20del=20albar=C3=A1n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci4/app/Controllers/Albaranes/Albaran.php | 19 +++++++++++++++++++ .../Models/Albaranes/AlbaranLineaModel.php | 2 +- .../themes/vuexy/pdfs/albaran-anonimo.php | 16 +++++++++++++++- ci4/app/Views/themes/vuexy/pdfs/albaran.php | 16 +++++++++++++++- .../js/safekat/components/albaranComponent.js | 3 +++ 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/ci4/app/Controllers/Albaranes/Albaran.php b/ci4/app/Controllers/Albaranes/Albaran.php index 99eda620..91915ead 100755 --- a/ci4/app/Controllers/Albaranes/Albaran.php +++ b/ci4/app/Controllers/Albaranes/Albaran.php @@ -476,10 +476,29 @@ class Albaran extends \App\Controllers\BaseResourceController $model_linea->update($id, $linea->toArray()); + if($fieldName == 'cajas'){ + $cajas = $model_linea->where('albaran_id', $linea->albaran_id) + ->where('cajas > 0') + ->select('SUM(cajas) as total_cajas') + ->get(); + + $albaranModel = model('App\Models\Albaranes\AlbaranModel'); + $albaran = $albaranModel->find($linea->albaran_id); + if($albaran != false) { + $albaran->cajas = $cajas->getRow()->total_cajas; + $albaran->user_updated_id = auth()->user()->id; + $albaran->updated_at = date('Y-m-d H:i:s'); + $albaranModel->update($linea->albaran_id, $albaran->toArray()); + } + } + $data = [ 'success' => true, 'message' => lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.', ]; + if($fieldName == 'cajas') { + $data['cajas'] = $cajas->getRow()->total_cajas; + }; return $this->respond($data); } else { diff --git a/ci4/app/Models/Albaranes/AlbaranLineaModel.php b/ci4/app/Models/Albaranes/AlbaranLineaModel.php index 6467be3c..9d49cd06 100755 --- a/ci4/app/Models/Albaranes/AlbaranLineaModel.php +++ b/ci4/app/Models/Albaranes/AlbaranLineaModel.php @@ -54,7 +54,7 @@ class AlbaranLineaModel extends \App\Models\BaseModel ->select( "t1.id, t1.titulo as titulo, t1.isbn as isbn, t1.ref_cliente as ref_cliente, t1.cantidad as unidades, t1.precio_unidad as precio_unidad, t1.iva_reducido as iva_reducido, - t1.total as total, pedidos.id AS pedido" + t1.total as total, pedidos.id AS pedido, t1.cajas, t1.unidades_cajas" ) ->join("pedidos_linea", "t1.pedido_linea_id = pedidos_linea.id", "left") ->join("pedidos", "pedidos_linea.pedido_id = pedidos.id", "left"); diff --git a/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php b/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php index db93eda4..7e7fed67 100644 --- a/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php +++ b/ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php @@ -63,7 +63,7 @@
- +
Cajas: cajas ?>Total cajas: cajas ?>
@@ -76,6 +76,8 @@ Título ISBN Ref. Cliente + Cajas + Unidades/Caja €/ud. Subtotal @@ -109,6 +111,12 @@
ref_cliente ?>
+ +
cajas ?>
+ + +
unidades_cajas ?>
+ titulo, "IVA")): ?> @@ -140,6 +148,12 @@
+ +
+ + +
+
diff --git a/ci4/app/Views/themes/vuexy/pdfs/albaran.php b/ci4/app/Views/themes/vuexy/pdfs/albaran.php index 00ebc343..07e61438 100755 --- a/ci4/app/Views/themes/vuexy/pdfs/albaran.php +++ b/ci4/app/Views/themes/vuexy/pdfs/albaran.php @@ -69,7 +69,7 @@ - Cajas: cajas ?> + Total cajas: cajas ?> @@ -82,6 +82,8 @@ Título ISBN Ref. Cliente + Cajas + Unidades/Caja €/ud. Subtotal @@ -115,6 +117,12 @@
ref_cliente ?>
+ +
cajas ?>
+ + +
unidades_cajas ?>
+ titulo, "IVA")): ?> @@ -146,6 +154,12 @@
+ +
+ + +
+
diff --git a/httpdocs/assets/js/safekat/components/albaranComponent.js b/httpdocs/assets/js/safekat/components/albaranComponent.js index 964a2053..598c96a7 100644 --- a/httpdocs/assets/js/safekat/components/albaranComponent.js +++ b/httpdocs/assets/js/safekat/components/albaranComponent.js @@ -511,6 +511,9 @@ class AlbaranComponent { }, (response) => { if (response.success) { this.table.ajax.reload(null, false); + if(response.cajas != null){ + $('#cajas_albaran_' + this.id).val(response.cajas); + } } else { Swal.fire({ title: 'Error', From 06ba0c05003d77df07a42ec8399a92cb9f61d698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Thu, 5 Jun 2025 23:48:21 +0200 Subject: [PATCH 122/127] realizados cambios para que se calcule el tiempo estimado --- .../Controllers/Produccion/Ordentrabajo.php | 2 ++ ci4/app/Services/ProductionService.php | 23 ++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ci4/app/Controllers/Produccion/Ordentrabajo.php b/ci4/app/Controllers/Produccion/Ordentrabajo.php index 0784d246..a244e000 100755 --- a/ci4/app/Controllers/Produccion/Ordentrabajo.php +++ b/ci4/app/Controllers/Produccion/Ordentrabajo.php @@ -116,6 +116,8 @@ class Ordentrabajo extends BaseController $bodyData = $this->request->getPost(); $validated = $this->validation->run($bodyData, "orden_trabajo_tarea"); if ($validated) { + $tareaEntity = $this->otTarea->find($bodyData["orden_trabajo_tarea_id"]); + $this->produccionService->init($tareaEntity->orden_trabajo_id); $r = $this->produccionService->updateOrdenTrabajoTarea($bodyData["orden_trabajo_tarea_id"], $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]); diff --git a/ci4/app/Services/ProductionService.php b/ci4/app/Services/ProductionService.php index 770190d8..e5304add 100755 --- a/ci4/app/Services/ProductionService.php +++ b/ci4/app/Services/ProductionService.php @@ -450,7 +450,7 @@ class ProductionService extends BaseService 'nombre' => lang('Produccion.end_cut'), 'maquina_id' => $maquina_id, 'orden' => $maquinaCorteEntity->orden_planning, - 'tiempo_estimado' => $this->tiempoCorteFinalEstimado($maquinaCorteEntity), + 'tiempo_estimado' => $this->tiempoEstimadoPorUnidad($maquinaCorteEntity), 'tiempo_real' => 0, 'is_corte' => true, 'tipo_corte' => "bobina", @@ -546,12 +546,14 @@ class ProductionService extends BaseService $ot_tareas = []; if (count($p_linea_maquinas) > 0) { $linea_maquina = $p_linea_maquinas[0]; //Se obtiene la primera máquina aunque tenga varias + $maquinaEntity = $this->maquinaModel->find($linea_maquina->id); $ot_tareas["orden_trabajo_id"] = $this->ot->id; $ot_tareas["presupuesto_acabado_id"] = $p_linea->id; $ot_tareas["nombre"] = $p_linea->tarifa()->nombre; $ot_tareas["orden"] = $linea_maquina->orden_planning ?? 100; $ot_tareas["maquina_id"] = $linea_maquina->id; $ot_tareas["imposicion_id"] = null; + $ot_tareas['tiempo_estimado'] = $this->tiempoEstimadoPorUnidad($maquinaEntity); $this->otTarea->insert($ot_tareas); $ot_tareas = []; } else { @@ -577,12 +579,14 @@ class ProductionService extends BaseService $ot_tareas = []; if (count($p_linea_maquinas) > 0) { $linea_maquina = $p_linea_maquinas[0]; //Se obtiene la primera máquina aunque tenga varias + $maquinaEntity = $this->maquinaModel->find($linea_maquina->id); $ot_tareas["orden_trabajo_id"] = $this->ot->id; $ot_tareas["presupuesto_manipulado_id"] = $p_linea->id; $ot_tareas["nombre"] = $p_linea->tarifa()->nombre; $ot_tareas["orden"] = $linea_maquina->orden_planning ?? 100; $ot_tareas["maquina_id"] = $linea_maquina->id; $ot_tareas["imposicion_id"] = null; + $ot_tareas['tiempo_estimado'] = $this->tiempoEstimadoPorUnidad($maquinaEntity); $this->otTarea->insert($ot_tareas); $ot_tareas = []; } else { @@ -608,12 +612,14 @@ class ProductionService extends BaseService $ot_tareas = []; if (count($p_linea_maquinas) > 0) { $linea_maquina = $p_linea_maquinas[0]; //Se obtiene la primera máquina aunque tenga varias + $maquinaEntity = $this->maquinaModel->find($linea_maquina->id); $ot_tareas["orden_trabajo_id"] = $this->ot->id; $ot_tareas["presupuesto_preimpresion_id"] = $p_linea->id; $ot_tareas["nombre"] = $p_linea->tarifa()->nombre; $ot_tareas["orden"] = $linea_maquina->orden_planning ?? 100; $ot_tareas["maquina_id"] = $linea_maquina->id; $ot_tareas["imposicion_id"] = null; + $ot_tareas['tiempo_estimado'] = $this->tiempoEstimadoPorUnidad($maquinaEntity); $this->otTarea->insert($ot_tareas); $ot_tareas = []; } else { @@ -639,12 +645,18 @@ class ProductionService extends BaseService $ot_tareas = []; if (count($p_linea_maquinas) > 0) { $linea_maquina = $p_linea_maquinas[0]; //Se obtiene la primera máquina aunque tenga varias + $maquinaEntity = $this->maquinaModel->find($linea_maquina->id); $ot_tareas["orden_trabajo_id"] = $this->ot->id; $ot_tareas["presupuesto_encuadernado_id"] = $p_linea->id; $ot_tareas["nombre"] = $p_linea->tarifa()->nombre; $ot_tareas["orden"] = $linea_maquina->orden_planning ?? 110; $ot_tareas["maquina_id"] = $linea_maquina->id; - $ot_tareas["tiempo_estimado"] = $p_linea->tiempo; + if($p_linea->tiempo <= 0){ + $ot_tareas["tiempo_estimado"] = $this->tiempoEstimadoPorUnidad($maquinaEntity); + } + else{ + $ot_tareas["tiempo_estimado"] = $p_linea->tiempo*3600; // El manipulado viene en horas + } $ot_tareas["tiempo_real"] = $p_linea->tiempo; $ot_tareas["imposicion_id"] = null; $this->otTarea->insert($ot_tareas); @@ -1115,6 +1127,11 @@ class ProductionService extends BaseService public function updateOrdenTrabajoTarea($tarea_id, $data): bool { + $tareaEntity = $this->otTarea->find($tarea_id); + if(isset($data['maquina_id']) && $tareaEntity->maquina_id != $data['maquina_id']) { + $maquinaEntity = $this->maquinaModel->find($data['maquina_id']); + $data['tiempo_estimado'] = $this->tiempoEstimadoPorUnidad($maquinaEntity); + } if (isset($data['maquina_id'])) { $maquina = model(MaquinaModel::class)->find($data['maquina_id']); $data['orden'] = $maquina->orden_planning; @@ -2424,7 +2441,7 @@ class ProductionService extends BaseService * @param MaquinaEntity $maquina * @return float $seconds */ - public function tiempoCorteFinalEstimado(MaquinaEntity $maquina): float + public function tiempoEstimadoPorUnidad(MaquinaEntity $maquina): float { $seconds = 0; if ($this->presupuesto->tirada > 0) { From 5a9326ae825019aaf2f83fef164b061e9311c537 Mon Sep 17 00:00:00 2001 From: imnavajas Date: Fri, 6 Jun 2025 09:06:28 +0200 Subject: [PATCH 123/127] =?UTF-8?q?A=C3=B1adido=20helper=20de=20gestion=20?= =?UTF-8?q?de=20assets=20caducados=20e=20implementado=20en=20CSS=20de=20PD?= =?UTF-8?q?Fs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci4/app/Controllers/BaseController.php | 2 +- ci4/app/Controllers/BaseResourceController.php | 2 +- ci4/app/Controllers/GoBaseController.php | 2 +- ci4/app/Helpers/assets_helper.php | 10 ++++++++++ ci4/app/Views/themes/vuexy/pdfs/albaran-anonimo.php | 2 +- ci4/app/Views/themes/vuexy/pdfs/albaran.php | 2 +- ci4/app/Views/themes/vuexy/pdfs/factura.php | 2 +- ci4/app/Views/themes/vuexy/pdfs/ferro.php | 2 +- ci4/app/Views/themes/vuexy/pdfs/orden_trabajo.php | 2 +- ci4/app/Views/themes/vuexy/pdfs/orden_trabajo_view.php | 2 +- ci4/app/Views/themes/vuexy/pdfs/presupuesto.php | 2 +- ci4/app/Views/themes/vuexy/pdfs/prototipo.php | 2 +- 12 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 ci4/app/Helpers/assets_helper.php diff --git a/ci4/app/Controllers/BaseController.php b/ci4/app/Controllers/BaseController.php index 3e1c82a1..11e04e12 100755 --- a/ci4/app/Controllers/BaseController.php +++ b/ci4/app/Controllers/BaseController.php @@ -35,7 +35,7 @@ class BaseController extends Controller * * @var array */ - protected $helpers = ['general', 'go_common', 'rbac']; + protected $helpers = ['general', 'go_common', 'rbac', 'assets']; /** * Constructor. diff --git a/ci4/app/Controllers/BaseResourceController.php b/ci4/app/Controllers/BaseResourceController.php index ce3d7952..2da29e8b 100755 --- a/ci4/app/Controllers/BaseResourceController.php +++ b/ci4/app/Controllers/BaseResourceController.php @@ -85,7 +85,7 @@ abstract class BaseResourceController extends \CodeIgniter\RESTful\ResourceContr * * @var array */ - protected $helpers = ['session', 'go_common', 'form', 'text', 'general', 'rbac']; //JJO + protected $helpers = ['session', 'go_common', 'form', 'text', 'general', 'rbac', 'assets']; //JJO /** * Initializer method. diff --git a/ci4/app/Controllers/GoBaseController.php b/ci4/app/Controllers/GoBaseController.php index 992edbb4..8de2426b 100755 --- a/ci4/app/Controllers/GoBaseController.php +++ b/ci4/app/Controllers/GoBaseController.php @@ -139,7 +139,7 @@ abstract class GoBaseController extends Controller * * @var array */ - protected $helpers = ['session', 'go_common', 'text', 'general', 'jwt', 'rbac']; //JJO + protected $helpers = ['session', 'go_common', 'text', 'general', 'jwt', 'rbac', 'assets']; //JJO public static $queries = []; diff --git a/ci4/app/Helpers/assets_helper.php b/ci4/app/Helpers/assets_helper.php new file mode 100644 index 00000000..4f1631e0 --- /dev/null +++ b/ci4/app/Helpers/assets_helper.php @@ -0,0 +1,10 @@ + - +