mirror of
https://github.com/retailcrm/prestashop-module.git
synced 2025-03-01 19:03:14 +03:00
Fix mixed payments
This commit is contained in:
parent
273efdaab0
commit
35bccc98b4
@ -182,13 +182,8 @@ class RetailcrmHistory
|
||||
*/
|
||||
public static function ordersHistory()
|
||||
{
|
||||
$default_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT');
|
||||
|
||||
$lastSync = Configuration::get('RETAILCRM_LAST_ORDERS_SYNC');
|
||||
$lastDate = Configuration::get('RETAILCRM_LAST_SYNC');
|
||||
$references = new RetailcrmReferences(self::$api);
|
||||
$receiveOrderNumber = (bool)(Configuration::get(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING));
|
||||
$sendOrderNumber = (bool)(Configuration::get(RetailCRM::ENABLE_ORDER_NUMBER_SENDING));
|
||||
|
||||
if ($lastSync === false && $lastDate === false) {
|
||||
$filter = array(
|
||||
@ -228,6 +223,10 @@ class RetailcrmHistory
|
||||
}
|
||||
|
||||
if (count($historyChanges)) {
|
||||
$default_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT');
|
||||
$references = new RetailcrmReferences(self::$api);
|
||||
$receiveOrderNumber = (bool)(Configuration::get(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING));
|
||||
$sendOrderNumber = (bool)(Configuration::get(RetailCRM::ENABLE_ORDER_NUMBER_SENDING));
|
||||
$statuses = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_STATUS'), true)));
|
||||
$cartStatus = (string)(Configuration::get('RETAILCRM_API_SYNCHRONIZED_CART_STATUS'));
|
||||
$deliveries = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_DELIVERY'), true)));
|
||||
@ -235,6 +234,11 @@ class RetailcrmHistory
|
||||
$deliveryDefault = json_decode(Configuration::get('RETAILCRM_API_DELIVERY_DEFAULT'), true);
|
||||
$paymentDefault = json_decode(Configuration::get('RETAILCRM_API_PAYMENT_DEFAULT'), true);
|
||||
|
||||
$paymentsCMS = [];
|
||||
foreach ($references->getSystemPaymentModules() as $paymentCMS) {
|
||||
$paymentsCMS[$paymentCMS['code']] = $paymentCMS['name'];
|
||||
}
|
||||
|
||||
$orders = RetailcrmHistoryHelper::assemblyOrder($historyChanges);
|
||||
RetailcrmLogger::writeDebugArray(__METHOD__, array('Assembled history:', $orders));
|
||||
|
||||
@ -271,54 +275,58 @@ class RetailcrmHistory
|
||||
}
|
||||
|
||||
// payment
|
||||
$paymentTypeCRM = null;
|
||||
$paymentId = null;
|
||||
$paymentType = null;
|
||||
if (isset($order['payments'])) {
|
||||
if (count($order['payments']) == 1) {
|
||||
if (count($order['payments']) === 1) {
|
||||
$paymentCRM = end($order['payments']);
|
||||
$payment = $paymentCRM['type'];
|
||||
$paymentTypeCRM = $paymentCRM['type'];
|
||||
} elseif (count($order['payments']) > 1) {
|
||||
foreach ($order['payments'] as $paymentCRM) {
|
||||
if (isset($paymentCRM['status']) && $paymentCRM['status'] != 'paid') {
|
||||
$payment = $paymentCRM['type'];
|
||||
if (isset($paymentCRM['status']) && $paymentCRM['status'] !== 'paid') {
|
||||
$paymentTypeCRM = $paymentCRM['type'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($paymentCRM);
|
||||
|
||||
$crmPaymentType = isset($payment) ? $payment : null;
|
||||
if (!is_null($crmPaymentType) &&
|
||||
array_key_exists($crmPaymentType, $payments) && !empty($payments[$crmPaymentType])) {
|
||||
if (Module::getInstanceByName($payments[$crmPaymentType])) {
|
||||
$paymentType = Module::getModuleName($payments[$crmPaymentType]);
|
||||
} else {
|
||||
$paymentType = $payments[$crmPaymentType];
|
||||
}
|
||||
|
||||
$paymentId = $payments[$crmPaymentType];
|
||||
}
|
||||
|
||||
if ($paymentDefault && (!isset($paymentId) || !$paymentId)) {
|
||||
$paymentId = $paymentDefault;
|
||||
}
|
||||
|
||||
if (!isset($paymentType) || !$paymentType) {
|
||||
if ($paymentDefault) {
|
||||
if (Module::getInstanceByName($paymentDefault)) {
|
||||
$paymentType = Module::getModuleName($paymentDefault);
|
||||
} else {
|
||||
$paymentType = $paymentDefault;
|
||||
}
|
||||
// todo move to separate function
|
||||
if ($paymentTypeCRM) {
|
||||
if (array_key_exists($paymentTypeCRM, $payments) && !empty($payments[$paymentTypeCRM])) {
|
||||
$paymentId = $payments[$paymentTypeCRM];
|
||||
} else {
|
||||
RetailcrmLogger::writeCaller(
|
||||
'orderHistory',
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
'set default payment(error in order where id = %d)',
|
||||
'unmapped payment type %s (error in order where id = %d)',
|
||||
$paymentTypeCRM,
|
||||
$order['id']
|
||||
)
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
} elseif ($paymentDefault) {
|
||||
$paymentId = $paymentDefault;
|
||||
} else {
|
||||
RetailcrmLogger::writeCaller(
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
'set default payment (error in order where id = %d)',
|
||||
$order['id']
|
||||
)
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($paymentId && isset($paymentsCMS[$paymentId])) {
|
||||
$paymentType = $paymentsCMS[$paymentId];
|
||||
} else {
|
||||
$paymentType = $paymentId;
|
||||
}
|
||||
|
||||
// delivery
|
||||
@ -332,7 +340,7 @@ class RetailcrmHistory
|
||||
$deliveryType = $deliveryDefault;
|
||||
} else {
|
||||
RetailcrmLogger::writeCaller(
|
||||
'orderHistory',
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
'set default delivery(error in order where id = %d)',
|
||||
$order['id']
|
||||
@ -346,7 +354,7 @@ class RetailcrmHistory
|
||||
$customer = null;
|
||||
$customerId = null;
|
||||
|
||||
if ($order['customer']['type'] == 'customer_corporate'
|
||||
if ($order['customer']['type'] === 'customer_corporate'
|
||||
&& RetailcrmTools::isCorporateEnabled()
|
||||
&& !empty($order['contact'])
|
||||
&& array_key_exists('externalId', $order['contact'])
|
||||
@ -594,37 +602,44 @@ class RetailcrmHistory
|
||||
foreach ($order['payments'] as $payment) {
|
||||
if (!isset($payment['externalId'])
|
||||
&& isset($payment['status'])
|
||||
&& $payment['status'] == 'paid'
|
||||
&& $payment['status'] === 'paid'
|
||||
) {
|
||||
$ptype = $payment['type'];
|
||||
$ptypes = $references->getSystemPaymentModules();
|
||||
$paymentTypeCRM = isset($payment['type']) ? $payment['type'] : null;
|
||||
$paymentType = null;
|
||||
$paymentId = null;
|
||||
|
||||
if ($payments[$ptype] != null) {
|
||||
foreach ($ptypes as $pay) {
|
||||
if ($pay['code'] == $payments[$ptype]) {
|
||||
$payType = $pay['name'];
|
||||
}
|
||||
if ($paymentTypeCRM) {
|
||||
if (array_key_exists($paymentTypeCRM, $payments) && !empty($payments[$paymentTypeCRM])) {
|
||||
$paymentId = $payments[$paymentTypeCRM];
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
$orderPayment = new OrderPayment();
|
||||
$orderPayment->payment_method = $payType;
|
||||
$orderPayment->order_reference = $newOrder->reference;
|
||||
$orderPayment->id_currency = $default_currency;
|
||||
$orderPayment->amount = $payment['amount'];
|
||||
$orderPayment->date_add = $payment['paidAt'];
|
||||
|
||||
RetailcrmLogger::writeDebug(
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
'<Order Reference: %s> %s::%s',
|
||||
$newOrder->reference,
|
||||
get_class($orderPayment),
|
||||
'save'
|
||||
)
|
||||
);
|
||||
|
||||
$orderPayment->save();
|
||||
} elseif ($paymentDefault) {
|
||||
$paymentId = $paymentDefault;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
$paymentType = isset($paymentsCMS[$paymentId]) ? $paymentsCMS[$paymentId] : $paymentId;
|
||||
|
||||
$orderPayment = new OrderPayment();
|
||||
$orderPayment->payment_method = $paymentType;
|
||||
$orderPayment->order_reference = $newOrder->reference;
|
||||
$orderPayment->id_currency = $default_currency;
|
||||
$orderPayment->amount = $payment['amount'];
|
||||
$orderPayment->date_add = $payment['paidAt'];
|
||||
|
||||
RetailcrmLogger::writeDebug(
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
'<Order Reference: %s> %s::%s',
|
||||
$newOrder->reference,
|
||||
get_class($orderPayment),
|
||||
'save'
|
||||
)
|
||||
);
|
||||
|
||||
$orderPayment->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -709,17 +724,17 @@ class RetailcrmHistory
|
||||
}
|
||||
|
||||
// collect order ids for single fix request
|
||||
array_push($orderFix, array('id' => $order['id'], 'externalId' => $newOrder->id));
|
||||
$orderFix[] = array('id' => $order['id'], 'externalId' => $newOrder->id);
|
||||
|
||||
// update order items ids in crm
|
||||
$newItemsIdsByOrderId[$newOrder->id] = $newItemsIds;
|
||||
|
||||
// collect orders id and reference if option sendOrderNumber enabled
|
||||
if ($sendOrderNumber) {
|
||||
array_push($updateOrderIds, array(
|
||||
$updateOrderIds[] = array(
|
||||
'externalId' => $newOrder->id,
|
||||
'number' => $newOrder->reference,
|
||||
));
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$order = $order_history;
|
||||
@ -839,12 +854,14 @@ class RetailcrmHistory
|
||||
$dtype = !empty($order['delivery']['code']) ? $order['delivery']['code'] : null;
|
||||
$dcost = !empty($order['delivery']['cost']) ? $order['delivery']['cost'] : null;
|
||||
|
||||
if ($dtype != null && (
|
||||
if (
|
||||
(
|
||||
$dtype !== null &&
|
||||
isset($deliveries[$dtype])
|
||||
&& $deliveries[$dtype] != null
|
||||
&& $deliveries[$dtype] != $orderToUpdate->id_carrier
|
||||
&& $deliveries[$dtype] !== null
|
||||
&& $deliveries[$dtype] !== $orderToUpdate->id_carrier
|
||||
)
|
||||
|| $dcost != null
|
||||
|| $dcost !== null
|
||||
) {
|
||||
if (property_exists($orderToUpdate, 'id_order_carrier')) {
|
||||
$idOrderCarrier = $orderToUpdate->id_order_carrier;
|
||||
@ -878,46 +895,52 @@ class RetailcrmHistory
|
||||
foreach ($order['payments'] as $payment) {
|
||||
if (!isset($payment['externalId'])
|
||||
&& isset($payment['status'])
|
||||
&& $payment['status'] == 'paid'
|
||||
&& $payment['status'] === 'paid'
|
||||
) {
|
||||
$ptype = $payment['type'];
|
||||
$ptypes = $references->getSystemPaymentModules();
|
||||
$paymentTypeCRM = isset($payment['type']) ? $payment['type'] : null;
|
||||
$paymentType = null;
|
||||
$paymentId = null;
|
||||
|
||||
if ($payments[$ptype] != null) {
|
||||
foreach ($ptypes as $pay) {
|
||||
if ($pay['code'] == $payments[$ptype]) {
|
||||
$payType = $pay['name'];
|
||||
}
|
||||
}
|
||||
|
||||
$paymentType = Module::getModuleName($payments[$ptype]);
|
||||
$orderToUpdate->payment = $paymentType != null ? $paymentType : $payments[$ptype];
|
||||
$orderPayment = new OrderPayment();
|
||||
$orderPayment->payment_method = $payType;
|
||||
$orderPayment->order_reference = $orderToUpdate->reference;
|
||||
|
||||
if (isset($payment['amount'])) {
|
||||
$orderPayment->amount = $payment['amount'];
|
||||
if ($paymentTypeCRM) {
|
||||
if (array_key_exists($paymentTypeCRM, $payments) && !empty($payments[$paymentTypeCRM])) {
|
||||
$paymentId = $payments[$paymentTypeCRM];
|
||||
} else {
|
||||
$orderPayment->amount = $orderToUpdate->total_paid;
|
||||
continue;
|
||||
}
|
||||
|
||||
$orderPayment->id_currency = $default_currency;
|
||||
$orderPayment->date_add =
|
||||
isset($payment['paidAt']) ? $payment['paidAt'] : date('Y-m-d H:i:s');
|
||||
|
||||
RetailcrmLogger::writeDebug(
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
'<Order Reference: %s> %s::%s',
|
||||
$orderToUpdate->reference,
|
||||
get_class($orderPayment),
|
||||
'save'
|
||||
)
|
||||
);
|
||||
|
||||
$orderPayment->save();
|
||||
} elseif ($paymentDefault) {
|
||||
$paymentId = $paymentDefault;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
$paymentType = isset($paymentsCMS[$paymentId]) ? $paymentsCMS[$paymentId] : $paymentId;
|
||||
|
||||
$orderToUpdate->payment = $paymentType;
|
||||
$orderPayment = new OrderPayment();
|
||||
$orderPayment->payment_method = $paymentType;
|
||||
$orderPayment->order_reference = $orderToUpdate->reference;
|
||||
|
||||
if (isset($payment['amount'])) {
|
||||
$orderPayment->amount = $payment['amount'];
|
||||
} else {
|
||||
$orderPayment->amount = $orderToUpdate->total_paid;
|
||||
}
|
||||
|
||||
$orderPayment->id_currency = $default_currency;
|
||||
$orderPayment->date_add =
|
||||
isset($payment['paidAt']) ? $payment['paidAt'] : date('Y-m-d H:i:s');
|
||||
|
||||
RetailcrmLogger::writeDebug(
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
'<Order Reference: %s> %s::%s',
|
||||
$orderToUpdate->reference,
|
||||
get_class($orderPayment),
|
||||
'save'
|
||||
)
|
||||
);
|
||||
|
||||
$orderPayment->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1139,10 +1162,10 @@ class RetailcrmHistory
|
||||
|
||||
// collect orders id and reference if option sendOrderNumber enabled
|
||||
if ($sendOrderNumber) {
|
||||
array_push($updateOrderIds, array(
|
||||
$updateOrderIds[] = array(
|
||||
'externalId' => $orderToUpdate->id,
|
||||
'number' => $orderToUpdate->reference,
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1357,13 +1380,15 @@ class RetailcrmHistory
|
||||
WHERE id_order = ' . pSQL((int)$order_id) . '
|
||||
AND product_id = ' . pSQL((int)$product_id) . '
|
||||
AND product_attribute_id = ' . pSQL((int)$product_attribute_id) . '
|
||||
AND id_order_detail = ' . pSQL((int)$id_order_detail));
|
||||
AND id_order_detail = ' . pSQL((int)$id_order_detail)
|
||||
);
|
||||
}
|
||||
|
||||
private static function getNewOrderDetailId()
|
||||
{
|
||||
return Db::getInstance()->getRow('
|
||||
SELECT MAX(id_order_detail) FROM ' . _DB_PREFIX_ . 'order_detail');
|
||||
SELECT MAX(id_order_detail) FROM ' . _DB_PREFIX_ . 'order_detail'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -753,7 +753,7 @@ class RetailcrmTools
|
||||
|
||||
foreach ($checkMapping as $field) {
|
||||
if ($first->$field != $second->$field) {
|
||||
RetailcrmLogger::writeDebug(__METHOD__, print_r(array(
|
||||
RetailcrmLogger::writeDebug(__METHOD__, json_encode(array(
|
||||
'first' => array(
|
||||
'id' => $first->id,
|
||||
$field => $first->$field
|
||||
@ -762,7 +762,7 @@ class RetailcrmTools
|
||||
'id' => $second->id,
|
||||
$field => $second->$field
|
||||
),
|
||||
), true));
|
||||
)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ class RetailCRM extends Module
|
||||
if (empty($existingOrder)) {
|
||||
$response = $this->api->ordersCreate($crmOrder);
|
||||
|
||||
if ($response->isSuccessful() && $receiveOrderNumber) {
|
||||
if ($response instanceof RetailcrmApiResponse && $response->isSuccessful() && $receiveOrderNumber) {
|
||||
$crmOrder = $response->order;
|
||||
$object->reference = $crmOrder['number'];
|
||||
$object->update();
|
||||
@ -862,7 +862,7 @@ class RetailCRM extends Module
|
||||
} else {
|
||||
$response = $this->api->ordersCreate($order);
|
||||
|
||||
if ($response->isSuccessful() && $receiveOrderNumber) {
|
||||
if ($response instanceof RetailcrmApiResponse && $response->isSuccessful() && $receiveOrderNumber) {
|
||||
$crmOrder = $response->order;
|
||||
$cmsOrder->reference = $crmOrder['number'];
|
||||
$cmsOrder->update();
|
||||
@ -894,28 +894,22 @@ class RetailCRM extends Module
|
||||
|
||||
public function hookActionPaymentCCAdd($params)
|
||||
{
|
||||
$payments = $this->reference->getSystemPaymentModules();
|
||||
$paymentCRM = json_decode(Configuration::get(static::PAYMENT), true);
|
||||
$payment = "";
|
||||
$payCode = "";
|
||||
$payments = array_filter(json_decode(Configuration::get(static::PAYMENT), true));
|
||||
$paymentType = false;
|
||||
$externalId = false;
|
||||
|
||||
foreach ($payments as $valPay) {
|
||||
if ($valPay['name'] == $params['paymentCC']->payment_method) {
|
||||
$payCode = $valPay['code'];
|
||||
foreach ($this->reference->getSystemPaymentModules() as $paymentCMS) {
|
||||
if (
|
||||
$paymentCMS['name'] === $params['paymentCC']->payment_method
|
||||
&& array_key_exists($paymentCMS['code'], $payments)
|
||||
&& !empty($payments[$paymentCMS['code']])
|
||||
) {
|
||||
$paymentType = $payments[$paymentCMS['code']];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($payCode) && array_key_exists($payCode, $paymentCRM) && !empty($paymentCRM[$payCode])) {
|
||||
$payment = $paymentCRM[$payCode];
|
||||
}
|
||||
|
||||
if (empty($payment)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$externalId = false;
|
||||
|
||||
if (empty($params['cart']) || empty((int) $params['cart']->id)) {
|
||||
if (!$paymentType || empty($params['cart']) || empty((int) $params['cart']->id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -925,12 +919,20 @@ class RetailCRM extends Module
|
||||
$externalId = RetailcrmTools::getCartOrderExternalId($params['cart']);
|
||||
} else {
|
||||
if (version_compare(_PS_VERSION_, '1.7.1.0', '>=')) {
|
||||
$id_order = (int)Order::getIdByCartId((int)$params['cart']->id);
|
||||
$id_order = (int) Order::getIdByCartId((int) $params['cart']->id);
|
||||
} else {
|
||||
$id_order = (int)Order::getOrderByCartId((int)$params['cart']->id);
|
||||
$id_order = (int) Order::getOrderByCartId((int) $params['cart']->id);
|
||||
}
|
||||
|
||||
if ($id_order > 0) {
|
||||
// do not update payment if the order in Cart and OrderPayment aren't the same
|
||||
if ($params['paymentCC']->order_reference) {
|
||||
$order = Order::getByReference($params['paymentCC']->order_reference)->getFirst();
|
||||
if (!$order || $order->id !== $id_order) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$response = $this->api->ordersGet($id_order);
|
||||
if ($response !== false && isset($response['order'])) {
|
||||
$externalId = $id_order;
|
||||
@ -938,38 +940,39 @@ class RetailCRM extends Module
|
||||
}
|
||||
}
|
||||
|
||||
if ($externalId === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status = (round($params['paymentCC']->amount, 2) > 0 ? 'paid' : null);
|
||||
$orderCRM = $response['order'];
|
||||
|
||||
if ($externalId !== false) {
|
||||
$orderCRM = $response['order'];
|
||||
|
||||
if ($orderCRM && $orderCRM['payments']) {
|
||||
foreach ($orderCRM['payments'] as $orderPayment) {
|
||||
if ($orderPayment['type'] == $payment) {
|
||||
$updatePayment = $orderPayment;
|
||||
$updatePayment['amount'] = $params['paymentCC']->amount;
|
||||
$updatePayment['paidAt'] = $params['paymentCC']->date_add;
|
||||
$updatePayment['status'] = $status;
|
||||
}
|
||||
if ($orderCRM && $orderCRM['payments']) {
|
||||
foreach ($orderCRM['payments'] as $orderPayment) {
|
||||
if ($orderPayment['type'] === $paymentType) {
|
||||
$updatePayment = $orderPayment;
|
||||
$updatePayment['amount'] = $params['paymentCC']->amount;
|
||||
$updatePayment['paidAt'] = $params['paymentCC']->date_add;
|
||||
$updatePayment['status'] = $status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($updatePayment)) {
|
||||
$this->api->ordersPaymentEdit($updatePayment, 'id');
|
||||
} else {
|
||||
$createPayment = array(
|
||||
'externalId' => $params['paymentCC']->id,
|
||||
'amount' => $params['paymentCC']->amount,
|
||||
'paidAt' => $params['paymentCC']->date_add,
|
||||
'type' => $payment,
|
||||
'status' => $status,
|
||||
'order' => array(
|
||||
'externalId' => $externalId,
|
||||
),
|
||||
);
|
||||
if (isset($updatePayment)) {
|
||||
$this->api->ordersPaymentEdit($updatePayment, 'id');
|
||||
} else {
|
||||
$createPayment = array(
|
||||
'externalId' => $params['paymentCC']->id,
|
||||
'amount' => $params['paymentCC']->amount,
|
||||
'paidAt' => $params['paymentCC']->date_add,
|
||||
'type' => $paymentType,
|
||||
'status' => $status,
|
||||
'order' => array(
|
||||
'externalId' => $externalId,
|
||||
),
|
||||
);
|
||||
|
||||
$this->api->ordersPaymentCreate($createPayment);
|
||||
}
|
||||
$this->api->ordersPaymentCreate($createPayment);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user