fichaje automatico y escaneo

This commit is contained in:
amazuecos
2025-05-05 00:47:00 +02:00
parent fb7f2a28d9
commit 305eea00e6
19 changed files with 821 additions and 25 deletions

View File

@ -762,6 +762,8 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func
$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('maquinas/ots/datatable/(:num)','Ordentrabajo::datatable_maquina_ordenes_trabajo/$1');
$routes->get('maquinas/ots/(:num)','Ordentrabajo::get_maquina_ots/$1');
/**======================
* UPDATES
*========================**/
@ -780,12 +782,17 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func
$routes->post("update/tarea/pliegos", "Ordentrabajo::update_orden_trabajo_pliegos");
$routes->post("update/tarea/proveedor", "Ordentrabajo::update_presupuesto_tarea_proveedor");
$routes->post("fa/tareas/finish", 'Ordentrabajo::update_orden_trabajo_fa_tareas');
$routes->post('maquinas/ots','Ordentrabajo::store_maquina_ordenes_trabajo');
$routes->post('maquinas/ots/estado','Ordentrabajo::update_maquina_ordenes_trabajo_estado');
/**DELETES */
$routes->delete("portada/(:num)", 'Ordentrabajo::delete_orden_trabajo_portada/$1');
$routes->delete("tarea/progress/(:num)", "Ordentrabajo::delete_orden_trabajo_progress_date/$1");
$routes->delete('reset/tareas/(:num)', 'Ordentrabajo::reset_tareas/$1');
$routes->delete('tareas/(:num)', 'Ordentrabajo::delete_tarea/$1');
$routes->delete('maquinas/ots/(:num)', 'Ordentrabajo::delete_maquina_orden_trabajo_tarea/$1');
$routes->delete('maquinas/ots/all/(:num)', 'Ordentrabajo::delete_maquina_orden_trabajo_all/$1');
/**======================
* FILES
*========================**/
@ -823,6 +830,8 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func
$routes->get('maquinas/view/auto/(:num)', 'Ordentrabajo::maquinista_maquina_tareas_fichaje_automatico/$1', ['as' => 'viewMaquinistaFichajeAutomatico']);
$routes->get('maquinas/view/scan/(:num)', 'Ordentrabajo::maquinista_maquina_tareas_scan/$1', ['as' => 'viewMaquinistaTareaScan']);
$routes->get('maquinas/view/tarea/(:num)', 'Ordentrabajo::maquinista_maquina_tarea_view/$1', ['as' => 'viewProduccionMaquinistaTareaView']);
$routes->get('maquinas/view/maquina/ot/tareas/(:num)', 'Ordentrabajo::maquinista_maquina_ot_tareas_view/$1', ['as' => 'viewProduccionMaquinistaOtTareasView']);
$routes->get('colas/view', 'Ordentrabajo::maquinista_colas_view', ['as' => 'viewProduccionMaquinistaColas']);
/** DATATABLE */

View File

@ -195,6 +195,17 @@ class Validation extends BaseConfig
"label" => "Click end"
],
];
public array $maquina_ordenes_trabajo = [
"ordenes_trabajo" => [
"rules" => "required",
"label" => "Orden trabajo"
],
"maquina_id" => [
"rules" => "required|integer",
"label" => "Máquina"
],
];
public array $chat_department =
[

View File

@ -5,6 +5,7 @@ namespace App\Controllers\Produccion;
use App\Controllers\BaseController;
use App\Models\Compras\ProveedorModel;
use App\Models\Configuracion\MaquinaModel;
use App\Models\Configuracion\MaquinaOtTareaModel;
use App\Models\OrdenTrabajo\OrdenTrabajoModel;
use App\Models\OrdenTrabajo\OrdenTrabajoTarea;
use App\Models\OrdenTrabajo\OrdenTrabajoUser;
@ -31,6 +32,7 @@ class Ordentrabajo extends BaseController
protected OrdenTrabajoTarea $otTarea;
protected ProveedorModel $proveedorModel;
protected MaquinaModel $maquinaModel;
protected MaquinaOtTareaModel $maquinaOtTareaModel;
protected UserModel $userModel;
protected Validation $validation;
protected static $viewPath = 'themes/vuexy/form/produccion/';
@ -47,6 +49,7 @@ class Ordentrabajo extends BaseController
$this->produccionService = new ProductionService();
$this->otTarea = model(OrdenTrabajoTarea::class);
$this->maquinaModel = model(MaquinaModel::class);
$this->maquinaOtTareaModel = model(MaquinaOtTareaModel::class);
$this->proveedorModel = model(ProveedorModel::class);
$this->validation = service("validation");
helper("time");
@ -375,8 +378,8 @@ class Ordentrabajo extends BaseController
->add("action", fn($q) => $q)
->edit("orden", fn($q) => ["id" => $q->id, "orden" => $q->orden])
->add("tarea_estado", fn($q) => $this->produccionService->getTitleTareaEstado($q->id))
->edit("tiempo_estimado", fn($q) => float_seconds_to_hhmm_string($q->tiempo_estimado))
->edit("tiempo_real", fn($q) => float_seconds_to_hhmm_string($q->tiempo_real))
->edit("tiempo_estimado", fn($q) => float_seconds_to_hhmmss_string($q->tiempo_estimado))
->edit("tiempo_real", fn($q) => float_seconds_to_hhmmss_string($q->tiempo_real))
->add("proveedor", fn($q) => $this->produccionService->getProveedorTarea($q->id))
->edit("maquina_tarea", fn($q) => ["id" => $q->id, "maquina_id" => $q->maquina_tarea, "maquina_name" => $q->maquina_nombre])
->add("imposicion", fn($q) => ["id" => $q->id, "imposicion_id" => $q->imposicion_id, "name" => $q->imposicion_name, "is_presupuesto_linea" => $q->presupuesto_linea_id ? true : false])
@ -601,8 +604,13 @@ class Ordentrabajo extends BaseController
['title' => $maquina->nombre, 'route' => route_to("viewProduccionMaquinistaMaquina", $maquina_id), 'active' => true],
];
$this->viewData["maquinaEntity"] = $maquina;
$tareasRunning = $this->maquinaOtTareaModel->queryDatatableJoinOrdenTrabajo($maquina->id)->countAllResults();
if ($tareasRunning) {
return view(static::$viewPath . '/maquinista/viewProduccionMaquinistaOtTareasView', $this->viewData);
} else {
return view(static::$viewPath . '/maquinista/viewMaquinistaMaquinaTareas', $this->viewData);
}
}
public function maquinista_maquina_tareas_fichaje_automatico(int $maquina_id)
{
$maquina = $this->maquinaModel->find($maquina_id);
@ -628,9 +636,19 @@ class Ordentrabajo extends BaseController
['title' => $otTareaEntity->nombre, 'route' => route_to("viewProduccionMaquinistaTareaView", $otTareaEntity->id), 'active' => true]
];
return view(static::$viewPath . '/maquinista/viewMaquinistaMaquinaTarea', $this->viewData);
}
public function maquinista_maquina_ot_tareas_view(int $maquina_id)
{
$maquinaEntity = $this->maquinaModel->find($maquina_id);
$this->viewData['maquinaEntity'] = $maquinaEntity;
$tareasRunning = $this->maquinaOtTareaModel->queryDatatableJoinOrdenTrabajo($maquina_id)->countAllResults();
if ($tareasRunning) {
return view(static::$viewPath . '/maquinista/viewProduccionMaquinistaOtTareasView', $this->viewData);
} else {
return view(static::$viewPath . '/maquinista/viewMaquinistaMaquinaTareas', $this->viewData);
}
}
public function maquinista_colas_view()
{
return view(static::$viewPath . '/maquinista/viewMaquinistaPlanningList', $this->viewData);
@ -722,9 +740,9 @@ class Ordentrabajo extends BaseController
return $this->response->setJSON(["message" => lang("App.global_alert_fetch_success"), "data" => $data]);
} else {
$tareasWithMaquina = $this->produccionService->init($orden_trabajo_id)->getTareasWithMaquina($maquina_id, ['F']);
if($tareasWithMaquina){
if ($tareasWithMaquina) {
return $this->response->setJSON(["message" => lang("Produccion.errors.tareas_finalizadas"), "data" => $tareasWithMaquina])->setStatusCode(400);
}else{
} else {
return $this->response->setJSON(["message" => lang("Produccion.errors.maquina_not_in_ot"), "data" => null])->setStatusCode(400);
}
}
@ -757,4 +775,120 @@ class Ordentrabajo extends BaseController
return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
}
}
public function store_maquina_ordenes_trabajo()
{
$bodyData = $this->request->getPost();
$validated = $this->validation->run($bodyData, "maquina_ordenes_trabajo");
if ($validated) {
$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();
if ($maquinaOtTarea) {
continue;
}
$this->maquinaOtTareaModel->insert(['maquina_id' => $validatedData['maquina_id'], 'orden_trabajo_id' => $orden_trabajo_id]);
}
return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => true, "data" => $validatedData]);
} else {
return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
}
}
public function update_maquina_ordenes_trabajo_estado()
{
$bodyData = $this->request->getPost();
$maquina_id = $bodyData['maquina_id'];
$estado = $bodyData['estado'];
$maquina_ots = $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->findAll();
$totalTareas = [];
foreach ($maquina_ots as $key => $maquina_ot) {
$tareas = $this->produccionService->init($maquina_ot->orden_trabajo_id)
->getTareasWithMaquina($maquina_id, ['P', 'I', 'S', 'D']);
foreach ($tareas as $key => $tarea) {
$this->produccionService->storeOrdenTrabajoTareaProgressDate(
[
'estado' => $estado,
'ot_tarea_id' => $tarea->id
]
);
$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);
$this->otTarea->save($tarea);
}
if ($estado == "F") {
$this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->delete();
}
return $this->response->setJSON(["message" => lang("Produccion.responses.update_maquina_ordenes_trabajo_estado")]);
}
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]);
}
public function delete_maquina_orden_trabajo_all($maquina_id)
{
$maquina_ots = $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->findAll();
foreach ($maquina_ots as $key => $maquina_ot) {
$tareas = $this->produccionService->init($maquina_ot->orden_trabajo_id)
->getTareasWithMaquina($maquina_id, ['P', 'I', 'S', 'D']);
foreach ($tareas as $key => $tarea) {
$this->produccionService->deleteOrdenTrabajoTareaProgressDates($tarea->id);
}
}
$status = $this->maquinaOtTareaModel->where('maquina_id',$maquina_id)->delete();
return $this->response->setJSON(["message" => lang("App.user_alert_delete"), "status" => $status]);
}
public function datatable_maquina_ordenes_trabajo($maquina_id)
{
$query = $this->maquinaOtTareaModel->queryDatatableJoinOrdenTrabajo($maquina_id);
return DataTable::of($query)
->add('action', fn($q) => $q->otId)
->add('titulo', fn($q) => $this->otModel->find($q->otId)->presupuesto()->titulo)
->add('barcode', fn($q) => $this->otModel->find($q->otId)->getBarCode())
->toJson(true);
}
public function get_maquina_ots($maquina_id)
{
$responseData = [
"tiempo_total_estimado" => 0,
"tiempo_total_real" => 0,
"clicks_total" => 0,
"tirada_total" => 0,
"estado" => "P",
];
$maquina_ots = $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->findAll();
foreach ($maquina_ots as $key => $maquina_ot) {
$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["estado"] = $tarea->lastState()->estado;
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);
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
use CodeIgniter\Database\RawSql;
class MaquinaOtTareasTable extends Migration
{
protected array $COLUMNS = [
'id' => [
'type' => 'INT',
'unsigned' => true,
'auto_increment' => true,
],
'maquina_id' => [
'type' => 'INT',
'unsigned' => true,
'constraint' => 11
],
'orden_trabajo_id' => [
'type' => 'INT',
'unsigned' => true,
],
];
public function up()
{
$this->forge->addField($this->COLUMNS);
$currenttime = new RawSql('CURRENT_TIMESTAMP');
$this->forge->addField([
'created_at' => [
'type' => 'TIMESTAMP',
'default' => $currenttime,
],
'updated_at' => [
'type' => 'TIMESTAMP',
'null' => true,
],
'deleted_at' => [
'type' => 'TIMESTAMP',
'null' => true,
],
]);
$this->forge->addPrimaryKey('id');
$this->forge->addForeignKey('maquina_id','lg_maquinas','id','CASCADE','CASCADE','maquina_ot_tareas_maquina_id_fk');
$this->forge->addForeignKey('orden_trabajo_id','ordenes_trabajo','id','CASCADE','CASCADE','maquina_ot_tareas_ot_id_fk');
$this->forge->createTable("maquina_ot_tareas");
}
public function down()
{
$this->forge->dropTable("maquina_ot_tareas");
}
}

View File

@ -21,7 +21,7 @@ class OrdenTrabajoTareaProgressDateEntity extends Entity
/**
* Orden de trabajo de la tarea
*
* @return OrdenTrabajoEntity
* @return OrdenTrabajoTareaEntity
*/
public function orden_trabajo_tarea() : OrdenTrabajoTareaEntity
{

View File

@ -0,0 +1,45 @@
<?php
namespace App\Entities\Tarifas\Maquinas;
use App\Entities\Configuracion\Maquina;
use App\Entities\Produccion\OrdenTrabajoEntity;
use App\Models\Configuracion\MaquinaModel;
use App\Models\OrdenTrabajo\OrdenTrabajoModel;
use CodeIgniter\Entity\Entity;
class MaquinaOtTareaEntity extends Entity
{
protected $attributes = [
"id" => null,
"maquina_id" => null,
"orden_trabajo_id" => null,
];
protected $casts = [
"id" => "integer",
"maquina_id" => "integer",
"orden_trabajo_id" => "integer",
];
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* Orden de trabajo
*
* @return OrdenTrabajoEntity
*/
public function orden_trabajo_tarea(): OrdenTrabajoEntity
{
$m = model(OrdenTrabajoModel::class);
return $m->find($this->attributes["orden_trabajo_id"]);
}
/**
* Maquina
*
* @return Maquina
*/
public function maquina(): Maquina
{
$m = model(MaquinaModel::class);
return $m->find($this->attributes["maquina_id"]);
}
}

View File

@ -10,7 +10,17 @@ function float_seconds_to_hhmm_string(?float $time):?string
}
return $time_str;
}
function float_seconds_to_hhmmss_string(?float $time): ?string
{
$time_str = null;
if ($time !== null) {
$hours = floor($time / 3600);
$minutes = floor(($time % 3600) / 60);
$seconds = floor($time % 60);
$time_str = sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds);
}
return $time_str;
}
function week_day_humanize(int $week_day,bool $upper = false) : string
{
$week_days = ["Lunes","Martes","Miércoles","Jueves","Viernes","Sábado","Domingo"];

View File

@ -164,7 +164,8 @@ return [
"placeholder_ot_id" => "Introduce el ID de la OT",
"fa_ot_input_form_text" => "Introduce una OT para terminar la actual e iniciar la siguiente.",
"scan_ot_input_form_text" => "Introduce una OT para añadirla al proceso",
"next_scan_ot" => "Comenzar"
"next_scan_ot" => "Comenzar",
"reset" => "Resetear"
],
@ -188,7 +189,11 @@ return [
"comentariosEncuadernacion" => "Comentarios encuadernación",
"comentariosLogistica" => "Comentarios logística",
"info_solapa_guillotina" => "Datos solapa y preparación guillotina",
"responses" => [
"finish_maquina_ordenes_trabajo" => "Tareas finalizadas correctamente",
"update_maquina_ordenes_trabajo_estado" => "Tareas actualizadas correctamente",
],
"errors" => [
"maquina_not_in_ot" => "Esta OT no tiene ninguna tarea con esta máquina",
"tareas_finalizadas" => "Las tareas de esta OT y máquina están marcadas como finalizadas",

View File

@ -404,7 +404,9 @@ class MaquinaModel extends \App\Models\BaseModel
->select([
'lg_maquinas.id as maquinaId',
'lg_maquinas.nombre',
'COUNT(tarea_progress.ot_tarea_id) as countTareas'
'COUNT(tarea_progress.ot_tarea_id) as countTareas',
'COUNT(maquina_ot_tareas.orden_trabajo_id) as countMaquinaTareas'
])
->join('orden_trabajo_tareas', 'orden_trabajo_tareas.maquina_id = lg_maquinas.id', 'left')
->join(
@ -420,6 +422,14 @@ class MaquinaModel extends \App\Models\BaseModel
'tarea_progress.ot_tarea_id = orden_trabajo_tareas.id',
'left'
)
->join(
"(SELECT orden_trabajo_id,deleted_at,maquina_id
FROM maquina_ot_tareas
WHERE deleted_at is NULL
) as maquina_ot_tareas",
'maquina_ot_tareas.maquina_id = lg_maquinas.id',
'left'
)
->join('ordenes_trabajo', 'ordenes_trabajo.id = orden_trabajo_tareas.orden_trabajo_id', 'left')
->join('pedidos', 'pedidos.id = ordenes_trabajo.pedido_id', 'left')
->where('lg_maquinas.tipo', $maquina_tipo)

View File

@ -0,0 +1,66 @@
<?php
namespace App\Models\Configuracion;
use App\Entities\Tarifas\Maquinas\MaquinaOtTareaEntity;
use App\Entities\Tarifas\Maquinas\TareaMaquinaEntity;
use CodeIgniter\Model;
class MaquinaOtTareaModel extends Model
{
protected $table = 'maquina_ot_tareas';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = MaquinaOtTareaEntity::class;
protected $useSoftDeletes = true;
protected $protectFields = true;
protected $allowedFields = [
"maquina_id",
"orden_trabajo_id",
];
protected bool $allowEmptyInserts = false;
protected bool $updateOnlyChanged = true;
protected array $casts = [];
protected array $castHandlers = [];
// Dates
protected $useTimestamps = true;
protected $dateFormat = 'datetime';
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $deletedField = 'deleted_at';
// Validation
protected $validationRules = [];
protected $validationMessages = [];
protected $skipValidation = false;
protected $cleanValidationRules = true;
// Callbacks
protected $allowCallbacks = true;
protected $beforeInsert = [];
protected $afterInsert = [];
protected $beforeUpdate = [];
protected $afterUpdate = [];
protected $beforeFind = [];
protected $afterFind = [];
protected $beforeDelete = [];
protected $afterDelete = [];
public function queryDatatableJoinOrdenTrabajo($maquina_id){
return $this->builder()
->select([
'maquina_ot_tareas.id as maquinaOtTareaId',
'ordenes_trabajo.id as otId'
])
->join('ordenes_trabajo','ordenes_trabajo.id = maquina_ot_tareas.orden_trabajo_id','left')
->where('maquina_ot_tareas.maquina_id',$maquina_id)
->where('maquina_ot_tareas.deleted_at',null);
}
}

View File

@ -1051,6 +1051,10 @@ class ProductionService extends BaseService
$this->init($tareaEntity->orden_trabajo_id);
$dateName = $this->getOrdenTrabajoTareaDate($tareaEntity);
$this->emptyOrdenTrabajoDate($this->ot->id, $dateName);
$tareaEntity->tiempo_real = 0;
$tareaEntity->click_init = 0;
$tareaEntity->click_end = 0;
$this->otTarea->save($tareaEntity);
}
if ($status) {
$response = $this->storeOrdenTrabajoTareaProgressDate($data);
@ -1482,6 +1486,7 @@ class ProductionService extends BaseService
}
return $uvi;
}
//TODO ACTUALIZAR
public function updateProgress(): bool
{
$userDates = $this->ordenTrabajoConfig->DATE_USER_MAPPING;

View File

@ -0,0 +1,55 @@
<div class="card h-100">
<div class="card-body">
<div class="row h-100">
<div class="col-6">
<div class="d-flex flex-column justify-content-evenly gap-2 h-100">
<div class="row mb-2">
<div class="col-md-6 mb-2">
<p class="mb-0">Tirada</p>
<h5 class="mb-0" id="tirada-info"></h5>
</div>
<div class="col-md-6 mb-2 <?= $maquinaEntity->tipo != "impresion" ? "d-none" : "" ?>" >
<p class="mb-0">Clicks</p>
<h5 class="mb-0" id="clicks-info"></h5>
</div>
</div>
<div class="row mb-2">
<div class="col-md-6">
<p class="mb-0 text-truncate">Tiempo estimado</p>
<h5 class="mb-0" id="tiempo-estimado-info"></h5>
</div>
<div class="col-md-6">
<p class="mb-0 text-truncate">Tiempo real</p>
<h5 class="mb-0" id="tiempo-real-info"></h5>
</div>
</div>
<div class="row" <?= $maquinaEntity->tipo != "impresion" ? "disabled" : "" ?>>
<div class="col-md-12 form-group form-group-lg">
<label for="input-click-init" class="form-label"><?= lang('Produccion.click_init') ?></label>
<input class="form-control input-lg ot-tarea-click" min="0" name="click_init" id="input-click-init" placeholder="<?= lang('Produccion.click_init') ?>" value="0">
</div>
<div class="col-md-12 form-group form-group-lg">
<label for="input-click-init" class="form-label input-lg"><?= lang('Produccion.click_end') ?></label>
<input class="form-control ot-tarea-click" min="0" name="click_end" id="input-click-end" placeholder="<?= lang('Produccion.click_end') ?>" value="0">
</div>
</div>
</div>
</div>
<div class="col-6 h-100">
<div class="d-flex flex-column justify-content-evenly gap-2 h-100">
<button type="button" data-estado="I" id="btn-start-tarea" class="maquina-btn btn btn-success w-100 d-flex justify-content-evenly action-btn"><span class="ti ti-player-play ti-lg"></span><?= lang('Produccion.maquinista.play_tarea') ?></button>
<button type="button" data-estado="S" id="btn-pause-tarea" class="maquina-btn btn btn-info w-100 d-flex justify-content-evenly d-none action-btn"><span class="ti ti-player-pause ti-lg"></span><?= lang('Produccion.maquinista.play_pause') ?></button>
<button type="button" data-estado="D" id="btn-stop-tarea" class="maquina-btn btn btn-warning w-100 d-flex justify-content-evenly"><span class="ti ti-player-stop ti-lg"></span><?= lang('Produccion.maquinista.play_stop') ?></button>
<button type="button" data-estado="F" id="btn-finish-tarea" class="maquina-btn btn btn-primary w-100 d-flex justify-content-evenly action-btn d-none"><span class="ti ti-player-eject ti-lg"></span><?= lang('Produccion.maquinista.play_end') ?></button>
<button type="button" id="btn-delete-tarea" class="maquina-btn btn btn-danger w-100 d-flex justify-content-evenly"><span class="ti ti-square-x ti-lg"></span><?= lang('Produccion.maquinista.cancel') ?></button>
</div>
</div>
</div>
</div>
</div>

View File

@ -18,7 +18,7 @@
<div class="row" id="maquinas-impresion">
<?php foreach ($maquinas["impresion"] as $key => $maquina): ?>
<div class="col-md-4 col-sm-2 col-lg-3 col-xs-12 mb-2 h-100 p-2">
<a href="<?= route_to("viewProduccionMaquinaTareasList", $maquina["maquinaId"]) ?>" type="button" class="maquina-btn btn btn-outline-primary w-100">
<a href="<?= route_to("viewProduccionMaquinaTareasList", $maquina["maquinaId"]) ?>" type="button" class="maquina-btn btn btn-outline-<?= $maquina['countMaquinaTareas'] > 0 ? "danger" : "primary" ?> w-100">
<span class="d-sm-inline-flex justify-content-between align-items-center gap-2">
<?= $maquina["nombre"] ?>
<?php if ($maquina["countTareas"] > 0): ?>
@ -39,7 +39,7 @@
<div class="row" id="maquinas-acabado">
<?php foreach ($maquinas["acabado"] as $key => $maquina): ?>
<div class="col-md-4 col-sm-2 col-lg-3 col-xs-12 mb-2 h-100 p-2">
<a href="<?= route_to("viewProduccionMaquinaTareasList", $maquina["maquinaId"]) ?>" type="button" class="maquina-btn btn btn-outline-primary w-100">
<a href="<?= route_to("viewProduccionMaquinaTareasList", $maquina["maquinaId"]) ?>" type="button" class="maquina-btn btn btn-outline-<?= $maquina['countMaquinaTareas'] > 0 ? "danger" : "primary" ?> w-100">
<span class="d-sm-inline-flex justify-content-between align-items-center gap-2">
<?= $maquina["nombre"] ?>
<?php if ($maquina["countTareas"] > 0): ?>
@ -60,7 +60,7 @@
<div class="row" id="maquinas-manipulado">
<?php foreach ($maquinas["manipulado"] as $key => $maquina): ?>
<div class="col-md-4 col-sm-2 col-lg-3 col-xs-12 mb-2 h-100 p-2">
<a href="<?= route_to("viewProduccionMaquinaTareasList", $maquina["maquinaId"]) ?>" type="button" class="maquina-btn btn btn-outline-primary w-100">
<a href="<?= route_to("viewProduccionMaquinaTareasList", $maquina["maquinaId"]) ?>" type="button" class="maquina-btn btn btn-outline-<?= $maquina['countMaquinaTareas'] > 0 ? "danger" : "primary" ?> w-100">
<span class="d-sm-inline-flex justify-content-between align-items-center gap-2">
<?= $maquina["nombre"] ?>
<?php if ($maquina["countTareas"] > 0): ?>

View File

@ -10,12 +10,21 @@
<div class="d-flex flex-row justify-content-end align-items-stretch mb-2 gap-2">
<a type="button" id="tarea-list-link" class="btn btn-primary" href="<?= route_to('viewProduccionMaquinaTareasList', $maquinaEntity->id) ?>"><span class="icon-base ti ti-list ti-xs me-1"></span> <?= lang('Produccion.maquinista.tarea_list') ?></a>
</div>
<div class="card">
<div class="card section-block">
<div class="card-body">
<h4 class="alert-heading d-flex align-items-center gap-1"><span style="color:red">ESCANEAR: </span><span class="fs-bold"><?= $maquinaEntity->nombre ?></span></h4>
<div class="row mb-2">
<?= view('themes/_commonPartialsBs/_alertBoxes'); ?>
<div class="row ot-scan-wrapper">
<div class="col-md-4">
<button type="button" class="btn btn-danger" id="btn-reset-ots">
<span class="icon-base ti ti-trash me-1"></span>
<?= lang('Produccion.maquinista.reset') ?>
</button>
</div>
</div>
<div class="row mb-2 ot-scan-wrapper">
<div class="col-md-8 mb-2">
<div class="table-responsive">
<table id="table-scanned-ots" class="table-maquinista table table-hover table-sm">
<thead>
@ -38,16 +47,23 @@
<div class="fs-medium fs-bold mt-2"><?= lang('Produccion.maquinista.scan_ot_input_form_text') ?></div>
</div>
<div class="col-md-12 mb-2">
<button type="button" class="maquina-btn btn btn-primary w-100">
<button type="button" class="maquina-btn btn btn-primary w-100" id="btn-save-maquina-ots" disabled>
<span class="icon-base ti ti-arrow-big-right me-1"></span>
<?= lang('Produccion.maquinista.next_scan_ot') ?>
</button>
</div>
</div>
</div>
<div class="col-md-12 d-none" id="ot-maquina-tareas-link">
<a class="maquina-btn btn btn-primary w-100" href="<?= route_to('viewProduccionMaquinistaOtTareasView', $maquinaEntity->id) ?>">
<span class="icon-base ti ti-arrow-big-right me-1"></span>
<?= lang('Produccion.maquinista.next_scan_ot') ?>
</a>
</div>
</div>
</div>
</div>
</div>
<?= $this->endSection() ?>

View File

@ -0,0 +1,81 @@
<?= $this->include('themes/_commonPartialsBs/select2bs5') ?>
<?= $this->include('themes/_commonPartialsBs/datatables') ?>
<?= $this->include('themes/_commonPartialsBs/sweetalert') ?>
<?= $this->include('themes/_commonPartialsBs/_confirm2delete') ?>
<?= $this->extend('themes/vuexy/main/defaultlayout') ?>
<?= $this->section('content'); ?>
<!--Content Body-->
<div class="row" id="viewProduccionMaquinistaOtTareasView" data-id="<?= $maquinaEntity->id ?>">
<div class="nav-align-top">
<ul class="nav nav-pills mb-4 nav-fill" role="tablist">
<li class="nav-item mb-1 mb-sm-0">
<button
type="button"
class="nav-link active"
role="tab"
data-bs-toggle="tab"
data-bs-target="#navs-tarea"
aria-controls="navs-tarea"
aria-selected="true">
<span class="d-none d-sm-inline-flex align-items-center">
<?= lang('Produccion.ots') ?>
</span>
<i class="icon-base ti tabler-home icon-sm d-sm-none"></i>
</button>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade show active" id="navs-tarea">
<div class="container-fluid h-100">
<?= view('themes/_commonPartialsBs/_alertBoxes'); ?>
<div class="row tarea-card-action-block">
<div class="col-md-6 mb-2">
<div class="table-responsive">
<table id="table-scanned-ots" class="table-maquinista table table-hover table-sm">
<thead>
<tr>
<th class="w-20"><?= lang('Produccion.datatable.ot_id') ?></th>
<th class="w-30"><?= lang('Produccion.datatable.titulo') ?></th>
<th class="w-40"><?= lang('Produccion.datatable.barcode') ?></th>
<th class="w-10"></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<div class="col-md-6 mb-2">
<?= view("/themes/vuexy/components/cards/tarea_multiple_card_actions.php") ?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?= $this->endSection() ?>
<?= $this->section('css') ?>
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/formvalidation/dist/css/formValidation.min.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/css/maquinista.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/notiflix/notiflix.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/spinkit/spinkit.css') ?>" />
<?= $this->endSection() ?>
<?= $this->section("additionalExternalJs") ?>
<script src="<?= site_url("themes/vuexy/vendor/libs/notiflix/notiflix.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/FormValidation.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/plugins/Bootstrap5.min.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/formvalidation/dist/js/plugins/AutoFocus.min.js") ?>"></script>
<script src="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.js') ?>"></script>
<script type="module" src="<?= site_url("/assets/js/safekat/pages/configuracion/maquinista/viewTareaMultipleView.js") ?>"></script>
<?= $this->endSection() ?>

View File

@ -0,0 +1,223 @@
import Ajax from '../../../components/ajax.js'
import { alertConfirmAction, alertError, alertSuccess } from '../../../components/alerts/sweetAlert.js'
class MaquinistaMultipleTarea {
constructor(domItem) {
this.item = domItem
this.maquinaId = this.item.data("id");
this.btnPlay = this.item.find("#btn-start-tarea")
this.btnPause = this.item.find("#btn-pause-tarea")
this.btnDelay = this.item.find("#btn-stop-tarea")
this.btnFinish = this.item.find("#btn-finish-tarea")
this.btnDeleteProgress = this.item.find("#btn-delete-tarea")
this.actionButtons = this.item.find('.action-btn')
this.tareaCardClass = '.tarea-card-action-block'
this.inputClick = $('.ot-tarea-click')
this.datatableItem = this.item.find('#table-scanned-ots')
this.datatableColumns = [
{ data: 'otId', searchable: false, sortable: false },
{ data: 'titulo', searchable: false, sortable: false },
{
data: 'barcode', searchable: false, sortable: false, render: (d, t) => {
return `<img class="img-fluid w-100 h-50" src="data:image/png;base64,${d}" alt="barcode" />`
}
},
{
data: 'action', searchable: false, sortable: false, render: (d, t) => {
return `<a href="/produccion/ordentrabajo/edit/${d}" type="button" title="OT" class="maquina-btn btn btn-primary d-flex justify-content-center gap-2"><span class="ti ti-eye ti-lg"></span></a>`
}
},
]
}
init() {
this.actionButtons.on('click', this.eventActionButton.bind(this))
this.btnDelay.on('click', this.delayEventActionButton.bind(this))
this.btnDeleteProgress.on('click', this.deleteAll.bind(this))
this.actionLoader(true)
this.datatableItem.DataTable({
processing: true,
dom: "",
serverSide: true,
ordering: false,
pageLength: 25,
language: {
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
},
columns: this.datatableColumns,
ajax: '/produccion/ordentrabajo/maquinas/ots/datatable/' + this.maquinaId,
});
this.initData()
}
async initData() {
try {
let responseData = await this.getMaquinaMultipleTarea();
this.fillCardData(responseData)
} catch (error) {
console.error(error)
} finally {
this.actionLoader(false)
}
}
fillCardData(responseData) {
this.item.find('#tirada-info').text(responseData?.tirada_total ?? 0)
this.item.find('#clicks-info').text(responseData?.clicks_total ?? 0)
this.item.find('#tiempo-estimado-info').text(responseData.tiempo_total_estimado ?? "00:00:00")
this.item.find('#tiempo-real-info').text(responseData.tiempo_total_real ?? "00:00:00")
this.showBasedOnStatus(responseData.estado)
}
async deleteAll() {
try {
let result = await alertConfirmAction('Se resetearán las tareas y se borrará el progreso')
if(result.isConfirmed){
let response = await this.deleteMaquinaOrdenesTrabajo()
popSuccessAlert(response.message);
window.location.reload();
}
} catch (error) {
console.error(error)
}
}
async eventActionButton(event) {
try {
this.actionLoader(true)
let statusClick = $(event.currentTarget).data('estado');
this.showBasedOnStatus(statusClick);
console.info(`Estado ${statusClick}`)
this.showBasedOnStatus(statusClick);
if (statusClick == "F") {
let result = await alertConfirmAction('Se marcarán como finalizadas todas las tareas')
if (result.isConfirmed == false) {
this.enableButtons()
throw new Error('Cancelado')
}
}
let response = await this.updateEstadoOts(statusClick)
popSuccessAlert(response.message)
let responseData = await this.getMaquinaMultipleTarea()
this.fillCardData(responseData)
if(statusClick == "F"){
window.location.reload();
}
} catch (error) {
console.error(error)
} finally {
this.actionLoader(false)
}
}
async delayEventActionButton(event) {
try {
this.actionLoader(true)
let statusClick = $(event.currentTarget).data('estado');
this.showBasedOnStatus(statusClick);
let response = await this.updateEstadoOts(statusClick)
popSuccessAlert(response.message)
let responseData = await this.getMaquinaMultipleTarea()
this.fillCardData(responseData)
} catch (error) {
console.error(error)
} finally {
this.actionLoader(false)
}
}
actionLoader(status = true) {
if (status) {
Notiflix.Block.circle(this.tareaCardClass);
} else {
Notiflix.Block.remove(this.tareaCardClass);
}
}
showPlay() {
this.btnPause.addClass('d-none')
this.btnPlay.removeClass('d-none')
this.btnFinish.removeClass('d-none')
this.btnDelay.removeClass('d-none')
}
showPause() {
this.btnPlay.addClass('d-none')
this.btnFinish.addClass('d-none')
this.btnPause.removeClass('d-none')
}
disableButtons() {
this.actionButtons.attr('disabled', 'disabled')
this.btnDelay.attr('disabled', 'disabled')
this.btnDeleteProgress.attr('disabled', 'disabled')
}
enableButtons() {
this.actionButtons.removeAttr('disabled')
this.btnDelay.removeAttr('disabled', 'disabled')
this.btnDeleteProgress.removeAttr('disabled', 'disabled')
}
showBasedOnStatus(status) {
if (['P', 'S'].includes(status)) {
this.enableButtons()
this.showPlay()
}
if (['F', 'E'].includes(status)) {
this.disableButtons()
this.showPlay()
}
if (status == 'I') {
this.enableButtons()
this.showPause()
}
if (status == "D") {
this.showPlay()
}
}
getClicks() {
return {
click_init: this.item.find('#input-click-init').val() ?? 0,
click_end: this.item.find('#input-click-end').val() ?? 0,
}
}
/** maquinas/ots/estado */
updateEstadoOts(estado) {
return new Promise((resolve, reject) => {
new Ajax('/produccion/ordentrabajo/maquinas/ots/estado',
{
maquina_id: this.maquinaId,
estado: estado,
...this.getClicks()
},
null,
resolve,
reject
).post()
})
}
getMaquinaMultipleTarea() {
return new Promise((resolve, reject) => {
new Ajax('/produccion/ordentrabajo/maquinas/ots/' + this.maquinaId,
null,
null,
resolve,
reject
).get()
})
}
deleteMaquinaOrdenesTrabajo() {
return new Promise((resolve, reject) => {
new Ajax('/produccion/ordentrabajo/maquinas/ots/all/' + this.maquinaId,
null,
null,
resolve,
reject
).delete()
})
}
}
export default MaquinistaMultipleTarea;

View File

@ -7,20 +7,26 @@ class MaquinistaScan {
this.item = domItem
/** ELEMENT DOM VARIABLES */
this.otInputId = this.item.find('#ot-id')
this.wrapperCard = this.item.find('#ot-fa-card')
this.otId = null
this.maquinaId = this.item.data("id")
this.ots = []
this.datatableItem = this.item.find('#table-scanned-ots')
this.btnSave = this.item.find('#btn-save-maquina-ots');
this.btnReset = this.item.find('#btn-reset-ots')
this.datatableColumns = [
{ data: 'id', searchable: false, sortable: false },
{ data: 'title', searchable: false, sortable: false },
]
this.datatableData = [];
this.linkAfterSave = this.item.find('#ot-maquina-tareas-link')
this.scanWrapper = this.item.find('.ot-scan-wrapper')
}
init() {
this.otInputId.trigger('focus')
this.otInputId.on('change', this.addOt.bind(this))
this.btnReset.on('click',this.reset.bind(this))
this.btnSave.on('click',this.saveMultipleOTs.bind(this))
this.datatable = this.datatableItem.DataTable({
processing: true,
serverSide: false,
@ -32,13 +38,20 @@ class MaquinistaScan {
columns: this.datatableColumns,
data: this.datatableData
});
}
hideCard() {
this.wrapperCard.addClass('d-none')
}
showCard() {
this.wrapperCard.removeClass('d-none')
reset(){
this.ots = []
this.datatable.clear()
this.datatable.draw()
this.reloadFocus();
this.btnSave.attr('disabled','disabled');
}
hideWrapper() {
this.scanWrapper.addClass('d-none')
}
showWrapper() {
this.scanWrapper.removeClass('d-none')
}
actionLoader(status = true) {
if (status) {
@ -47,10 +60,31 @@ class MaquinistaScan {
Notiflix.Block.remove('.section-block');
}
}
reloadFocus(){
reloadFocus() {
this.otInputId.val("")
this.otInputId.trigger('focus')
}
async saveMultipleOTs() {
try {
let result = await alertConfirmAction()
if(result.isConfirmed){
this.actionLoader(true)
let response = await this.postMaquinaOrdenesTrabajo()
this.actionLoader(false)
popSuccessAlert(response.message)
this.hideWrapper()
this.linkAfterSave.removeClass('d-none')
}
} catch (error) {
this.actionLoader(false)
if (error?.responseJSON) {
popErrorAlert(error.responseJSON.message)
} else {
popErrorAlert(error)
}
}
}
async addOt() {
try {
if (this.ots.includes(this.otInputId.val())) {
@ -67,6 +101,7 @@ class MaquinistaScan {
}])
this.datatable.draw()
this.reloadFocus()
this.btnSave.removeAttr('disabled')
}
} catch (error) {
@ -97,6 +132,26 @@ class MaquinistaScan {
}
postMaquinaOrdenesTrabajo() {
return new Promise((resolve, reject) => {
let ajax = new Ajax(
`/produccion/ordentrabajo/maquinas/ots`,
{
maquina_id: this.maquinaId,
ordenes_trabajo: this.ots
},
null,
(response) => {
resolve(response)
},
(error) => {
reject(error)
}
)
ajax.post();
})
}

View File

@ -0,0 +1,7 @@
import MaquinistaMultipleTarea from "./maquinistaMultipleTarea.js"
$(() => {
console.info("MAQUINISTA MAQUINA OT TAREAS")
let tareaMultiple = new MaquinistaMultipleTarea($("#viewProduccionMaquinistaOtTareasView"))
tareaMultiple.init()
})

View File

@ -4,6 +4,12 @@
width : 100%;
font-size : 20px;
}
.maquina-btn-v
{
height : 5rem;
width : 1rem;
font-size : 20px;
}
.table-maquinista td{
height : 7rem;
}