mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 05:02:36 +01:00
Event / Listeners for Purchase Orders
This commit is contained in:
parent
76bd11facb
commit
e6e651b4b4
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\PurchaseOrder;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PurchaseOrderWasMarkedSent.
|
||||
*/
|
||||
class PurchaseOrderWasMarkedSent
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var \App\Models\PurchaseOrder
|
||||
*/
|
||||
public $purchase_order;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrder $purchase_order, Company $company, array $event_vars)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ class PurchaseOrderWasRestored
|
||||
|
||||
public $event_vars;
|
||||
|
||||
public $fromDeleted;
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
@ -38,9 +39,10 @@ class PurchaseOrderWasRestored
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrder $purchase_order, Company $company, array $event_vars)
|
||||
public function __construct(PurchaseOrder $purchase_order, $fromDeleted, Company $company, array $event_vars)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->fromDeleted = $fromDeleted;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ class PurchaseOrderController extends BaseController
|
||||
|
||||
$purchase_orders = PurchaseOrder::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||
|
||||
if (! $invoices) {
|
||||
if (! $purchase_orders) {
|
||||
return response()->json(['message' => 'No Purchase Orders Found']);
|
||||
}
|
||||
|
||||
|
58
app/Listeners/PurchaseOrder/CreatePurchaseOrderActivity.php
Normal file
58
app/Listeners/PurchaseOrder/CreatePurchaseOrderActivity.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class CreatePurchaseOrderActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::CREATE_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderArchivedActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::ARCHIVE_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
58
app/Listeners/PurchaseOrder/PurchaseOrderDeletedActivity.php
Normal file
58
app/Listeners/PurchaseOrder/PurchaseOrderDeletedActivity.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderDeletedActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::DELETE_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
59
app/Listeners/PurchaseOrder/PurchaseOrderEmailActivity.php
Normal file
59
app/Listeners/PurchaseOrder/PurchaseOrderEmailActivity.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://purchase_orderninja.com).
|
||||
*
|
||||
* @link https://github.com/purchase_orderninja/purchase_orderninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://purchase_orderninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderEmailActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->invitation->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->purchase_order_id = $event->invitation->purchase_order->id;
|
||||
$fields->company_id = $event->invitation->purchase_order->company_id;
|
||||
$fields->vendor_contact_id = $event->invitation->purchase_order->vendor_contact_id;
|
||||
$fields->vendor_id = $event->invitation->purchase_order->vendor_id;
|
||||
$fields->activity_type_id = Activity::EMAIL_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->invitation->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderRestoredActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::RESTORE_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
62
app/Listeners/PurchaseOrder/PurchaseOrderViewedActivity.php
Normal file
62
app/Listeners/PurchaseOrder/PurchaseOrderViewedActivity.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderViewedActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->invitation->purchase_order->user_id;
|
||||
|
||||
$event->invitation->purchase_order->service()->markSent()->save();
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->company_id = $event->invitation->company_id;
|
||||
$fields->activity_type_id = Activity::VIEW_PURCHASE_ORDER;
|
||||
$fields->vendor_id = $event->invitation->purchase_order->vendor_id;
|
||||
$fields->vendor_contact_id = $event->invitation->vendor_contact_id;
|
||||
$fields->invitation_id = $event->invitation->id;
|
||||
$fields->purchase_order_id = $event->invitation->purchase_order_id;
|
||||
|
||||
$this->activity_repo->save($fields, $event->invitation->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
58
app/Listeners/PurchaseOrder/UpdatePurchaseOrderActivity.php
Normal file
58
app/Listeners/PurchaseOrder/UpdatePurchaseOrderActivity.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class UpdatePurchaseOrderActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDB($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::UPDATE_PURCHASE_ORDER;
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
@ -178,6 +178,13 @@ use App\Listeners\Payment\PaymentEmailFailureActivity;
|
||||
use App\Listeners\Payment\PaymentEmailedActivity;
|
||||
use App\Listeners\Payment\PaymentNotification;
|
||||
use App\Listeners\Payment\PaymentRestoredActivity;
|
||||
use App\Listeners\PurchaseOrder\CreatePurchaseOrderActivity;
|
||||
use App\Listeners\PurchaseOrder\PurchaseOrderArchivedActivity;
|
||||
use App\Listeners\PurchaseOrder\PurchaseOrderDeletedActivity;
|
||||
use App\Listeners\PurchaseOrder\PurchaseOrderEmailActivity;
|
||||
use App\Listeners\PurchaseOrder\PurchaseOrderRestoredActivity;
|
||||
use App\Listeners\PurchaseOrder\PurchaseOrderViewedActivity;
|
||||
use App\Listeners\PurchaseOrder\UpdatePurchaseOrderActivity;
|
||||
use App\Listeners\Quote\QuoteApprovedActivity;
|
||||
use App\Listeners\Quote\QuoteApprovedNotification;
|
||||
use App\Listeners\Quote\QuoteApprovedWebhook;
|
||||
@ -444,20 +451,25 @@ class EventServiceProvider extends ServiceProvider
|
||||
PaymentEmailFailureActivity::class,
|
||||
],
|
||||
PurchaseOrderWasArchived::class => [
|
||||
PurchaseOrderArchivedActivity::class,
|
||||
],
|
||||
PurchaseOrderWasCreated::class => [
|
||||
CreatePurchaseOrderActivity::class,
|
||||
],
|
||||
PurchaseOrderWasDeleted::class => [
|
||||
PurchaseOrderDeletedActivity::class,
|
||||
],
|
||||
PurchaseOrderWasEmailed::class => [
|
||||
],
|
||||
PurchaseOrderWasMarkedSent::class => [
|
||||
PurchaseOrderEmailActivity::class,
|
||||
],
|
||||
PurchaseOrderWasRestored::class => [
|
||||
PurchaseOrderRestoredActivity::class,
|
||||
],
|
||||
PurchaseOrderWasUpdated::class => [
|
||||
UpdatePurchaseOrderActivity::class,
|
||||
],
|
||||
PurchaseOrderWasViewed::class => [
|
||||
PurchaseOrderViewedActivity::class,
|
||||
],
|
||||
CompanyDocumentsDeleted::class => [
|
||||
DeleteCompanyDocuments::class,
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
namespace App\Services\PurchaseOrder;
|
||||
|
||||
|
||||
use App\Events\PurchaseOrder\PurchaseOrderWasMarkedSent;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Utils\Ninja;
|
||||
|
||||
@ -46,8 +44,6 @@ class MarkSent
|
||||
// ->touchPdf()
|
||||
->save();
|
||||
|
||||
event(new PurchaseOrderWasMarkedSent($this->purchase_order, $this->purchase_order->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
return $this->purchase_order;
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ class PurchaseOrderTransformer extends EntityTransformer
|
||||
'custom_surcharge_tax3' => (bool)$purchase_order->custom_surcharge_tax3,
|
||||
'custom_surcharge_tax4' => (bool)$purchase_order->custom_surcharge_tax4,
|
||||
'line_items' => $purchase_order->line_items ?: (array)[],
|
||||
'entity_type' => 'credit',
|
||||
'entity_type' => 'purchase_order',
|
||||
'exchange_rate' => (float)$purchase_order->exchange_rate,
|
||||
'paid_to_date' => (float)$purchase_order->paid_to_date,
|
||||
'subscription_id' => $this->encodePrimaryKey($purchase_order->subscription_id),
|
||||
|
@ -57,6 +57,10 @@ class CreatePurchaseOrderInvitationsTable extends Migration
|
||||
$table->unsignedInteger('client_id')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('activities', function (Blueprint $table) {
|
||||
$table->unsignedInteger('purchase_order_id')->nullable();
|
||||
$table->unsignedInteger('vendor_contact_id')->nullable();
|
||||
});
|
||||
|
||||
Company::cursor()->each(function ($company){
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user