mirror of
https://git.imnavajas.es/jjimenez/safekat.git
synced 2025-07-25 22:52:08 +00:00
feat : duplicar papel impresion con relaciones
This commit is contained in:
@ -276,6 +276,7 @@ $routes->group('papelesimpresion', ['namespace' => 'App\Controllers\Configuracio
|
|||||||
$routes->post('datatable', 'Papelesimpresion::datatable', ['as' => 'dataTableOfPapelesImpresion']);
|
$routes->post('datatable', 'Papelesimpresion::datatable', ['as' => 'dataTableOfPapelesImpresion']);
|
||||||
$routes->post('allmenuitems', 'Papelesimpresion::allItemsSelect', ['as' => 'select2ItemsOfPapelesImpresion']);
|
$routes->post('allmenuitems', 'Papelesimpresion::allItemsSelect', ['as' => 'select2ItemsOfPapelesImpresion']);
|
||||||
$routes->post('menuitems', 'Papelesimpresion::menuItems', ['as' => 'menuItemsOfPapelesImpresion']);
|
$routes->post('menuitems', 'Papelesimpresion::menuItems', ['as' => 'menuItemsOfPapelesImpresion']);
|
||||||
|
$routes->post('duplicate/(:num)','Papelesimpresion::duplicate/$1',['as' => 'duplicatePapelImpresion']);
|
||||||
});
|
});
|
||||||
$routes->resource('papelesimpresion', ['namespace' => 'App\Controllers\Configuracion', 'controller' => 'Papelesimpresion', 'except' => 'show,new,create,update']);
|
$routes->resource('papelesimpresion', ['namespace' => 'App\Controllers\Configuracion', 'controller' => 'Papelesimpresion', 'except' => 'show,new,create,update']);
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
namespace Config;
|
namespace Config;
|
||||||
|
|
||||||
use App\Services\FTPService;
|
use App\Services\FTPService;
|
||||||
|
use App\Services\PapelImpresionService;
|
||||||
use CodeIgniter\Config\BaseService;
|
use CodeIgniter\Config\BaseService;
|
||||||
use App\Services\ProductionService;
|
use App\Services\ProductionService;
|
||||||
use App\Services\TarifaMaquinaService;
|
use App\Services\TarifaMaquinaService;
|
||||||
@ -38,4 +39,8 @@ class Services extends BaseService
|
|||||||
public static function tarifa_maquina(){
|
public static function tarifa_maquina(){
|
||||||
return new TarifaMaquinaService();
|
return new TarifaMaquinaService();
|
||||||
}
|
}
|
||||||
|
public static function papel_impresion()
|
||||||
|
{
|
||||||
|
return new PapelImpresionService();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,6 +43,14 @@ class Validation extends BaseConfig
|
|||||||
// Rules
|
// Rules
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PapelImpresion duplicate validation
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public array $papel_impresion_duplicate = [
|
||||||
|
"name" => "required|string"
|
||||||
|
];
|
||||||
/**========================================================================
|
/**========================================================================
|
||||||
* TARIFA MAQUINA ACABADO
|
* TARIFA MAQUINA ACABADO
|
||||||
*========================================================================**/
|
*========================================================================**/
|
||||||
|
|||||||
@ -22,6 +22,7 @@ use
|
|||||||
|
|
||||||
|
|
||||||
use App\Models\Collection;
|
use App\Models\Collection;
|
||||||
|
use CodeIgniter\Validation\Validation;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -35,7 +36,6 @@ use App\Models\Configuracion\PapelImpresionTipologiaModel;
|
|||||||
use App\Models\Configuracion\MaquinasPapelesImpresionModel;
|
use App\Models\Configuracion\MaquinasPapelesImpresionModel;
|
||||||
use App\Models\Configuracion\MaquinaModel;
|
use App\Models\Configuracion\MaquinaModel;
|
||||||
|
|
||||||
|
|
||||||
class Papelesimpresion extends \App\Controllers\BaseResourceController
|
class Papelesimpresion extends \App\Controllers\BaseResourceController
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -52,6 +52,7 @@ class Papelesimpresion extends \App\Controllers\BaseResourceController
|
|||||||
protected static $viewPath = 'themes/vuexy/form/configuracion/papel/';
|
protected static $viewPath = 'themes/vuexy/form/configuracion/papel/';
|
||||||
|
|
||||||
protected $indexRoute = 'papelImpresionList';
|
protected $indexRoute = 'papelImpresionList';
|
||||||
|
protected Validation $validation;
|
||||||
|
|
||||||
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
|
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
|
||||||
{
|
{
|
||||||
@ -66,6 +67,7 @@ class Papelesimpresion extends \App\Controllers\BaseResourceController
|
|||||||
$this->delete_flag = 1;
|
$this->delete_flag = 1;
|
||||||
|
|
||||||
$this->tpModel = new PapelImpresionTipologiaModel();
|
$this->tpModel = new PapelImpresionTipologiaModel();
|
||||||
|
$this->validation = service("validation");
|
||||||
|
|
||||||
// Breadcrumbs
|
// Breadcrumbs
|
||||||
$this->viewData['breadcrumb'] = [
|
$this->viewData['breadcrumb'] = [
|
||||||
@ -443,4 +445,27 @@ class Papelesimpresion extends \App\Controllers\BaseResourceController
|
|||||||
$ma_pa_model->updateRows($active_values);
|
$ma_pa_model->updateRows($active_values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Duplica el papel impresion y sus relaciones
|
||||||
|
*
|
||||||
|
* @param int $papel_impresion_id
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function duplicate( int $papel_impresion_id)
|
||||||
|
{
|
||||||
|
$bodyData = $this->request->getPost();
|
||||||
|
$validated = $this->validation->run($bodyData, "papel_impresion_duplicate");
|
||||||
|
if($validated){
|
||||||
|
$papelImpresionEntity = $this->model->find($papel_impresion_id);
|
||||||
|
$papelImpresionService = service('papel_impresion');
|
||||||
|
$duplicated = $papelImpresionService
|
||||||
|
->setPapelImpresionEntity($papelImpresionEntity)
|
||||||
|
->duplicate($bodyData["name"]);
|
||||||
|
return $this->response->setJSON(["data" => $duplicated]);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace App\Entities\Configuracion;
|
namespace App\Entities\Configuracion;
|
||||||
|
|
||||||
|
use App\Models\Configuracion\MaquinasPapelesImpresionModel;
|
||||||
|
use App\Models\Configuracion\PapelImpresionMargenModel;
|
||||||
|
use App\Models\Configuracion\PapelImpresionTipologiaModel;
|
||||||
use CodeIgniter\Entity;
|
use CodeIgniter\Entity;
|
||||||
|
|
||||||
class PapelImpresion extends \CodeIgniter\Entity\Entity
|
class PapelImpresion extends \CodeIgniter\Entity\Entity
|
||||||
@ -49,4 +52,20 @@ class PapelImpresion extends \CodeIgniter\Entity\Entity
|
|||||||
"use_for_tapa_dura" => "boolean",
|
"use_for_tapa_dura" => "boolean",
|
||||||
"is_deleted" => "int",
|
"is_deleted" => "int",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function tipologia() : ?PapelImpresionTipologia
|
||||||
|
{
|
||||||
|
$m = model(PapelImpresionTipologiaModel::class);
|
||||||
|
return $m->where('papel_impresion_id',$this->attributes["id"])->first();
|
||||||
|
}
|
||||||
|
public function maquinas_impresion() : ?MaquinasPapelesImpresionEntity
|
||||||
|
{
|
||||||
|
$m = model(MaquinasPapelesImpresionModel::class);
|
||||||
|
return $m->where('papel_impresion_id',$this->attributes["id"])->first();
|
||||||
|
}
|
||||||
|
public function margen() : ?PapelImpresionMargen
|
||||||
|
{
|
||||||
|
$m = model(PapelImpresionMargenModel::class);
|
||||||
|
return $m->where('papel_impresion_id',$this->attributes["id"])->first();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,8 @@ return [
|
|||||||
'Profile' => 'Perfil',
|
'Profile' => 'Perfil',
|
||||||
'Roles' => 'Roles',
|
'Roles' => 'Roles',
|
||||||
'Save' => 'Guardar',
|
'Save' => 'Guardar',
|
||||||
|
'Copy' => 'Copiar',
|
||||||
|
'Duplicate' => 'Duplicar',
|
||||||
'Sections' => 'Secciones',
|
'Sections' => 'Secciones',
|
||||||
'SignOut' => 'Desconectar',
|
'SignOut' => 'Desconectar',
|
||||||
'Success' => 'Éxito',
|
'Success' => 'Éxito',
|
||||||
|
|||||||
@ -39,6 +39,7 @@ return [
|
|||||||
'activo' => 'Activo?',
|
'activo' => 'Activo?',
|
||||||
'useInClient' => 'Usar en presup. cliente',
|
'useInClient' => 'Usar en presup. cliente',
|
||||||
'userUpdateId' => 'ID usuario actualización',
|
'userUpdateId' => 'ID usuario actualización',
|
||||||
|
'namePlaceholderDuplicated' => 'Inserte el nombre del papel que se va a duplicar',
|
||||||
|
|
||||||
'consumo_tintas_rotativas' => 'Consumo tintas',
|
'consumo_tintas_rotativas' => 'Consumo tintas',
|
||||||
'maquinas_papel' => 'Máquinas seleccionadas',
|
'maquinas_papel' => 'Máquinas seleccionadas',
|
||||||
|
|||||||
66
ci4/app/Services/PapelImpresionService.php
Normal file
66
ci4/app/Services/PapelImpresionService.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Entities\Configuracion\PapelImpresion;
|
||||||
|
use App\Models\Configuracion\MaquinasPapelesImpresionModel;
|
||||||
|
use App\Models\Configuracion\PapelImpresionMargenModel;
|
||||||
|
use App\Models\Configuracion\PapelImpresionModel;
|
||||||
|
use App\Models\Configuracion\PapelImpresionTipologiaModel;
|
||||||
|
use CodeIgniter\Config\BaseService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PapelImpresionService extends BaseService
|
||||||
|
{
|
||||||
|
|
||||||
|
protected PapelImpresionModel $papelImpresionModel;
|
||||||
|
protected PapelImpresionTipologiaModel $papelImpresionTipologiaModel;
|
||||||
|
protected MaquinasPapelesImpresionModel $maquinaPapelImpresionModel;
|
||||||
|
protected PapelImpresionMargenModel $papelImpresionMargenModel;
|
||||||
|
protected MaquinasPapelesImpresionModel $papelImpresionMaquinaModel;
|
||||||
|
|
||||||
|
|
||||||
|
protected PapelImpresion $papelImpresion;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->papelImpresionModel = model(PapelImpresionModel::class);
|
||||||
|
$this->papelImpresionModel = model(PapelImpresionModel::class);
|
||||||
|
$this->papelImpresionMargenModel = model(PapelImpresionMargenModel::class);
|
||||||
|
$this->papelImpresionTipologiaModel = model(PapelImpresionTipologiaModel::class);
|
||||||
|
$this->papelImpresionMaquinaModel = model(MaquinasPapelesImpresionModel::class);
|
||||||
|
}
|
||||||
|
public function setPapelImpresionEntity(PapelImpresion $papelImpresionEntity) : self
|
||||||
|
{
|
||||||
|
$this->papelImpresion = $papelImpresionEntity;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function duplicate(string $newName) : PapelImpresion
|
||||||
|
{
|
||||||
|
$papelImpresionRow = $this->papelImpresion?->toArray();
|
||||||
|
$papelImpresionMargen = $this->papelImpresion->margen()?->toArray();
|
||||||
|
$papelImpresionTipologia = $this->papelImpresion->tipologia()?->toArray();
|
||||||
|
$papelImpresionMaquina = $this->papelImpresion->maquinas_impresion()?->toArray();
|
||||||
|
|
||||||
|
$papelImpresionRow['nombre'] = $newName;
|
||||||
|
if($this->papelImpresion){
|
||||||
|
$papelImpresionDuplicatedId = $this->papelImpresionModel->insert($papelImpresionRow);
|
||||||
|
}
|
||||||
|
if($papelImpresionMargen){
|
||||||
|
$papelImpresionMargen['papel_impresion_id'] = $papelImpresionDuplicatedId;
|
||||||
|
$this->papelImpresionMargenModel->insert($papelImpresionMargen);
|
||||||
|
}
|
||||||
|
if($papelImpresionTipologia){
|
||||||
|
$this->papelImpresionTipologiaModel->insert($papelImpresionTipologia);
|
||||||
|
$papelImpresionTipologia['papel_impresion_id'] = $papelImpresionDuplicatedId;
|
||||||
|
}
|
||||||
|
if($papelImpresionMaquina){
|
||||||
|
$papelImpresionMaquina['papel_impresion_id'] = $papelImpresionDuplicatedId;
|
||||||
|
$this->papelImpresionMaquinaModel->insert($papelImpresionMaquina);
|
||||||
|
}
|
||||||
|
$papelImpresionDuplicated = $this->papelImpresionModel->find($papelImpresionDuplicatedId);
|
||||||
|
return $papelImpresionDuplicated;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title"><?= $boxTitle ?? $pageTitle ?></h3>
|
<h3 class="card-title"><?= $boxTitle ?? $pageTitle ?></h3>
|
||||||
</div><!--//.card-header -->
|
</div><!--//.card-header -->
|
||||||
<form id="papelImpresionForm" method="post" class="card-body" action="<?= $formAction ?>">
|
<form id="papelImpresionForm" data-id="<?= $papelImpresion->id ?>" method="post" class="card-body" action="<?= $formAction ?>">
|
||||||
<?= csrf_field() ?>
|
<?= csrf_field() ?>
|
||||||
<?= view("themes/_commonPartialsBs/_alertBoxes") ?>
|
<?= view("themes/_commonPartialsBs/_alertBoxes") ?>
|
||||||
<?= !empty($validation->getErrors()) ? $validation->listErrors("bootstrap_style") : "" ?>
|
<?= !empty($validation->getErrors()) ? $validation->listErrors("bootstrap_style") : "" ?>
|
||||||
@ -19,8 +19,8 @@
|
|||||||
<input type="submit"
|
<input type="submit"
|
||||||
class="btn btn-primary float-start me-sm-3 me-1"
|
class="btn btn-primary float-start me-sm-3 me-1"
|
||||||
name="save"
|
name="save"
|
||||||
value="<?= lang("Basic.global.Save") ?>"
|
value="<?= lang("Basic.global.Save") ?>" />
|
||||||
/>
|
<button type="button" id="btn-papel-impresion-duplicate" class="btn btn-danger me-sm-3 me-1"><i class="ti ti-xs ti-copy"></i><?= lang("Basic.global.Duplicate") ?></button>
|
||||||
<?= anchor(route_to("papelImpresionList"), lang("Basic.global.Cancel"), ["class" => "btn btn-secondary"]) ?>
|
<?= anchor(route_to("papelImpresionList"), lang("Basic.global.Cancel"), ["class" => "btn btn-secondary"]) ?>
|
||||||
|
|
||||||
</div><!-- /.card-footer -->
|
</div><!-- /.card-footer -->
|
||||||
@ -106,8 +106,7 @@
|
|||||||
data-bs-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
data-bs-target="#accordionMaq"
|
data-bs-target="#accordionMaq"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="accordionMaq"
|
aria-controls="accordionMaq">
|
||||||
>
|
|
||||||
<p><?= lang("PapelImpresion.maquinas_papel") ?></p>
|
<p><?= lang("PapelImpresion.maquinas_papel") ?></p>
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
@ -134,11 +133,39 @@
|
|||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div><!--//.col -->
|
</div><!--//.col -->
|
||||||
|
<div class="modal fade" id="modalPapelImpresionDuplicate" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3><?= lang('Basic.global.Duplicate') ?></h3>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label for="duplicated_name"><?= lang("PapelImpresion.nombre") ?></label>
|
||||||
|
<input type="text" id="duplicated_name" name="name" class="form-control" placeholder="<?=lang("PapelImpresion.namePlaceholderDuplicated")?>">
|
||||||
|
<div class="invalid-feedback d-none">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="d-flex align-items-center justify-content-end gap-2">
|
||||||
|
<button type="button" id="btn-new-papel-impresion-duplicate" class="btn-primary btn btn-md"><?= lang('Basic.global.Save') ?></button>
|
||||||
|
<button type="button" class="btn-secondary btn btn-md" data-bs-dismiss="modal"><?= lang('Basic.global.Cancel') ?></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div><!--//.row -->
|
</div><!--//.row -->
|
||||||
|
|
||||||
<?= $this->endSection() ?>
|
<?= $this->endSection() ?>
|
||||||
|
|
||||||
|
|
||||||
|
<?= $this->section('additionalExternalJs') ?>
|
||||||
|
<script type="module" src="<?= site_url('assets/js/safekat/pages/configuracion/papel_impresion/duplicate.js') ?>"></script>
|
||||||
|
<?= $this->endSection() ?>
|
||||||
<!------------------------------------------->
|
<!------------------------------------------->
|
||||||
<!-- Código JS para general -->
|
<!-- Código JS para general -->
|
||||||
<!------------------------------------------->
|
<!------------------------------------------->
|
||||||
@ -288,7 +315,9 @@
|
|||||||
lengthChange: false,
|
lengthChange: false,
|
||||||
searching: false,
|
searching: false,
|
||||||
info: false,
|
info: false,
|
||||||
"dom": '<"mt-4"><"float-end"B><"float-start"l><t><"mt-4 mb-3"p>',
|
dom: "lftp",
|
||||||
|
|
||||||
|
|
||||||
stateSave: true,
|
stateSave: true,
|
||||||
language: {
|
language: {
|
||||||
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
|
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
|
||||||
@ -494,7 +523,9 @@
|
|||||||
lengthChange: false,
|
lengthChange: false,
|
||||||
searching: false,
|
searching: false,
|
||||||
info: false,
|
info: false,
|
||||||
"dom": '<"mt-4"><"float-end"B><"float-start"l><t><"mt-4 mb-3"p>',
|
dom: "lftp",
|
||||||
|
|
||||||
|
|
||||||
stateSave: true,
|
stateSave: true,
|
||||||
language: {
|
language: {
|
||||||
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
|
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
|
||||||
@ -787,5 +818,5 @@
|
|||||||
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/pdfmake/pdfmake.min.js") ?>" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/pdfmake/pdfmake.min.js") ?>" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/pdfmake/vfs_fonts.js") ?>"></script>
|
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/pdfmake/vfs_fonts.js") ?>"></script>
|
||||||
<script src="<?= site_url('themes/vuexy/js/datatables-editor/dataTables.editor.min.js') ?>"></script>
|
<script src="<?= site_url('themes/vuexy/js/datatables-editor/dataTables.editor.min.js') ?>"></script>
|
||||||
<?=$this->endSection() ?>
|
|
||||||
|
|
||||||
|
<?= $this->endSection() ?>
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import Ajax from "../../../components/ajax.js"
|
||||||
|
import Modal from "../../../components/modal.js";
|
||||||
|
$(() => {
|
||||||
|
let papelImpresionId = $("#papelImpresionForm").data("id");
|
||||||
|
const uri = '/configuracion/papelesimpresion/duplicate/' + papelImpresionId;
|
||||||
|
let modalPapelDuplicate = new Modal($("#modalPapelImpresionDuplicate"))
|
||||||
|
$("#btn-papel-impresion-duplicate").on("click", (event) => {
|
||||||
|
modalPapelDuplicate.toggle();
|
||||||
|
$("#btn-new-papel-impresion-duplicate").on("click", () => {
|
||||||
|
let name = $("#duplicated_name").val()
|
||||||
|
const ajax = new Ajax(uri,
|
||||||
|
{ name: name },
|
||||||
|
null,
|
||||||
|
(response) => {
|
||||||
|
modalPapelDuplicate.toggle();
|
||||||
|
$("#btn-new-papel-impresion-duplicate").off();
|
||||||
|
$("#duplicated_name").addClass("is-valid").removeClass('d-none');
|
||||||
|
window.open('/configuracion/papelesimpresion/edit/' + response.data.id)
|
||||||
|
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
$("#duplicated_name").removeClass("is-valid").addClass("is-invalid")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
ajax.post()
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user