fix some bugs
This commit is contained in:
@@ -20,7 +20,11 @@
|
||||
/>
|
||||
</MobileCardList>
|
||||
|
||||
<TransactionMobileDetailSheet v-model:visible="sheetVisible" :item="selectedItem" />
|
||||
<TransactionMobileDetailSheet
|
||||
v-model:visible="sheetVisible"
|
||||
:item="selectedItem"
|
||||
:metals="catalogMetals"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -32,6 +36,9 @@ import { useMobileTableList } from '@/components/mobile/composables/useMobileTab
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import TransactionMobileDetailSheet from './TransactionMobileDetailSheet.vue'
|
||||
import TransactionMobileListItem from './TransactionMobileListItem.vue'
|
||||
import type { TransactionMetalColumn } from '../hooks/transactionsColumns'
|
||||
|
||||
const catalogMetals = ref<TransactionMetalColumn[]>([])
|
||||
|
||||
const props = defineProps<{
|
||||
customerId?: number
|
||||
@@ -51,7 +58,10 @@ function fetchTransactions(params: TableInput) {
|
||||
hidden: false
|
||||
})
|
||||
}
|
||||
return getTransactionTable(params)
|
||||
return getTransactionTable(params).then((data) => {
|
||||
catalogMetals.value = data?.catalogMetals ?? []
|
||||
return data
|
||||
})
|
||||
}
|
||||
|
||||
const { loading, search, items, hasMore, reload, loadMore, fetch } = useMobileTableList<Transaction>({
|
||||
|
||||
@@ -3,21 +3,29 @@
|
||||
<template #default="{ item: row }">
|
||||
<MobileSheetHeader :title="sheetTitle" :subtitle="dateLabel(row)" :show-title="isMobile" />
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="rounded-lg border px-2 py-0.5 text-xs font-600" :class="typeTagClass(row)">
|
||||
{{ typeLabel(row) }}
|
||||
</span>
|
||||
<span
|
||||
v-if="!isMoneyType(row) && row.transaction_metal_label"
|
||||
class="rounded-lg border border-amber-300 bg-amber-50 px-2 py-0.5 text-xs font-600 text-amber-700"
|
||||
>
|
||||
{{ row.transaction_metal_label }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<MobileStatCard
|
||||
v-for="entry in metalEntries(row)"
|
||||
:key="entry.metal_id"
|
||||
bordered
|
||||
:variant="(row.gold ?? 0) > 0 ? 'success' : 'danger'"
|
||||
label="مقدار طلا (گرم)"
|
||||
:value="goldLabel(row)"
|
||||
:variant="entry.value > 0 ? 'success' : 'danger'"
|
||||
:label="transactionMetalAmountTitle(entry.metal_id, entry.label)"
|
||||
:value="entry.display"
|
||||
>
|
||||
<template #prefix>
|
||||
<BaseIcon icon="vuesax-linear:coin" size="18" :color="(row.gold ?? 0) > 0 ? '#15803d' : '#dc2626'" />
|
||||
<BaseIcon icon="vuesax-linear:coin" size="18" :color="entry.value > 0 ? '#15803d' : '#dc2626'" />
|
||||
</template>
|
||||
</MobileStatCard>
|
||||
<MobileStatCard
|
||||
@@ -33,6 +41,7 @@
|
||||
</div>
|
||||
|
||||
<MobileInfoGrid>
|
||||
<MobileDetailRow label="نوع فلز" :value="isMoneyType(row) ? '-' : (row.transaction_metal_label ?? '-')" />
|
||||
<MobileDetailRow label="کد تراکنش" :value="row.id ?? '-'" />
|
||||
<MobileDetailRow label="نام تراکنش" :value="row.type_str || '-'" />
|
||||
<MobileDetailRow label="علت تراکنش" full-width :value="noteLabel(row)" />
|
||||
@@ -53,10 +62,14 @@ import MobileStatCard from '@/components/mobile/MobileStatCard.vue'
|
||||
import { isMobile } from '@core/utils/is'
|
||||
import { toJalaliNoTime } from '@core/utils/useDataTime'
|
||||
import { usePrice } from '@core/utils/usePrice'
|
||||
import { metalLabel, transactionMetalAmountTitle } from '@/utils/adminMetalLabels'
|
||||
import { formatMetalDisplayValue, metalCellValue } from '@/utils/metalWeight'
|
||||
import type { TransactionMetalColumn } from '../hooks/transactionsColumns'
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
item: Transaction | null
|
||||
metals?: TransactionMetalColumn[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -75,7 +88,7 @@ function isMoneyType(row: Transaction) {
|
||||
}
|
||||
|
||||
function typeLabel(row: Transaction) {
|
||||
return isMoneyType(row) ? 'پول' : 'طلا'
|
||||
return isMoneyType(row) ? 'پول' : 'فلز'
|
||||
}
|
||||
|
||||
function typeTagClass(row: Transaction) {
|
||||
@@ -88,14 +101,26 @@ function dateLabel(row: Transaction) {
|
||||
return row.created_at ? toJalaliNoTime(row.created_at) : '-'
|
||||
}
|
||||
|
||||
function goldLabel(row: Transaction) {
|
||||
const gold = row.gold
|
||||
if (gold == null) return '-'
|
||||
return `${Number(Number(gold).toFixed(3))} گرم`
|
||||
}
|
||||
|
||||
function noteLabel(row: Transaction) {
|
||||
if (row.note == null) return '-'
|
||||
return String(row.note)
|
||||
}
|
||||
|
||||
function metalEntries(row: Transaction) {
|
||||
const metals = props.metals?.length
|
||||
? props.metals
|
||||
: [{ metal_id: row.transaction_metal_id ?? 1, label: row.transaction_metal_label ?? 'طلا' }]
|
||||
|
||||
return metals
|
||||
.map((metal) => {
|
||||
const value = metalCellValue(row as Record<string, unknown>, metal.metal_id)
|
||||
return {
|
||||
metal_id: metal.metal_id,
|
||||
label: metal.label,
|
||||
value,
|
||||
display: value ? formatMetalDisplayValue(value, metal.metal_id) : '-'
|
||||
}
|
||||
})
|
||||
.filter((entry) => entry.value !== 0)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
<span class="shrink-0 rounded-md border px-1.5 py-0.5 text-xs font-600" :class="typeTagClass">
|
||||
{{ typeLabel }}
|
||||
</span>
|
||||
<span
|
||||
v-if="!isMoneyType && item.transaction_metal_label"
|
||||
class="shrink-0 rounded-md border border-amber-300 bg-amber-50 px-1.5 py-0.5 text-xs font-600 text-amber-700"
|
||||
>
|
||||
{{ item.transaction_metal_label }}
|
||||
</span>
|
||||
<span class="truncate text-sm font-700 text-gray-900">{{ item.type_str || '-' }}</span>
|
||||
</div>
|
||||
<span class="shrink-0 text-xs text-gray-400">{{ dateLabel }}</span>
|
||||
@@ -31,7 +37,7 @@ defineEmits<{
|
||||
}>()
|
||||
|
||||
const isMoneyType = computed(() => props.item.type === 4 || props.item.type === 3)
|
||||
const typeLabel = computed(() => (isMoneyType.value ? 'پول' : 'طلا'))
|
||||
const typeLabel = computed(() => (isMoneyType.value ? 'پول' : 'فلز'))
|
||||
const typeTagClass = computed(() =>
|
||||
isMoneyType.value
|
||||
? 'border-green-300 bg-green-50 text-green-700'
|
||||
|
||||
@@ -67,7 +67,7 @@ import type {TableInput} from '@core/type/baseTable'
|
||||
import useBaseTable from '@core/components/BaseTableOld/hooks/useBaseTable'
|
||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
import {changeCustomerActivation, getCustomerTable} from '@/api/customer'
|
||||
import {cols} from '../hooks/transactionsColumns'
|
||||
import { buildTransactionsColumns } from '../hooks/transactionsColumns'
|
||||
import {useUserStore} from '@/store/userStore'
|
||||
import {usePrefix} from '@core/composable/usePrefix'
|
||||
import {message} from 'ant-design-vue'
|
||||
@@ -102,23 +102,24 @@ const {prefixCls} = usePrefix('pophoverstatus')
|
||||
const table = ref(null)
|
||||
|
||||
const tblProps = ref<any>({
|
||||
columns: cols,
|
||||
api: (params: TableInput) => {
|
||||
// console.log(props.customerId)
|
||||
columns: buildTransactionsColumns(),
|
||||
api: async (params: TableInput) => {
|
||||
if (props.customerId) {
|
||||
params.filters = []
|
||||
params.filters?.push({
|
||||
field: "customer_id",
|
||||
type: "text",
|
||||
field: 'customer_id',
|
||||
type: 'text',
|
||||
value: props.customerId,
|
||||
cr: "and",
|
||||
op: "eq",
|
||||
cr: 'and',
|
||||
op: 'eq',
|
||||
hidden: false
|
||||
})
|
||||
}
|
||||
return getTransactionTable(params)
|
||||
const data = await getTransactionTable(params)
|
||||
const metals = data?.catalogMetals ?? []
|
||||
tblProps.value.columns = buildTransactionsColumns(metals)
|
||||
return data
|
||||
}
|
||||
//bordered: true
|
||||
})
|
||||
const loading = ref<boolean>(false)
|
||||
/*async function changeCustomerActivationFunction(id: number) {
|
||||
|
||||
@@ -1,203 +1,165 @@
|
||||
import type {BaseTableColumn} from '@core/type/baseTable'
|
||||
import {toJalaliNoTime, toTime} from '@core/utils/useDataTime'
|
||||
import type { BaseTableColumn } from '@core/type/baseTable'
|
||||
import { toJalaliNoTime } from '@core/utils/useDataTime'
|
||||
import CustomTag from '@/components/CustomTag.vue'
|
||||
import {usePrice} from '@core/utils/usePrice'
|
||||
/*import BudgetSelect from '@/components/BudgetSelect.vue'
|
||||
import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
import type { FilterSelect } from '@/model/filterSelect'
|
||||
import type { DocItem } from '@/model/docType'*/
|
||||
import { usePrice } from '@core/utils/usePrice'
|
||||
import { metalLabel, transactionMetalAmountTitle } from '@/utils/adminMetalLabels'
|
||||
import { formatMetalDisplayValuePlain, metalCellValue } from '@/utils/metalWeight'
|
||||
|
||||
//define store
|
||||
//const store = useStaticApiListsStore()
|
||||
//document types
|
||||
/*let docTypes: DocItem[]*/
|
||||
/*onMounted(async () => {
|
||||
docTypes = await store.readyDocTypeList()
|
||||
})
|
||||
const filteredDocTypes: FilterSelect = docTypes?.map((x: DocItem) => {
|
||||
return {
|
||||
label: x.title,
|
||||
value: x.id
|
||||
export type TransactionMetalColumn = { metal_id: number; label: string; display_unit?: string }
|
||||
|
||||
function renderSignedMetalCell(value: number, metalId: number) {
|
||||
if (!value) {
|
||||
return (
|
||||
<div class="flex justify-center">
|
||||
<div class="px-6">0</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})*/
|
||||
|
||||
export const cols: BaseTableColumn[] = [
|
||||
{
|
||||
title: 'ردیف',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
filterable: false,
|
||||
sortable: false,
|
||||
customRender: (record: any) => {
|
||||
return record.index + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'کد تراکنش',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
type: 'Number'
|
||||
// className: 'column-money'
|
||||
},
|
||||
{
|
||||
title: 'نام تراکنش',
|
||||
dataIndex: 'type_str',
|
||||
key: 'type_str',
|
||||
type: 'Text'
|
||||
// className: 'column-money'
|
||||
},
|
||||
{
|
||||
title: 'علت تراکنش',
|
||||
dataIndex: 'note',
|
||||
key: 'note',
|
||||
type: 'Text',
|
||||
const cls = value > 0 ? 'text-green' : 'text-red'
|
||||
const formatted = formatMetalDisplayValuePlain(Math.abs(value), metalId)
|
||||
|
||||
return (
|
||||
<div class="flex justify-center">
|
||||
<div class={`font-bold px-6 ${cls}`}>{value > 0 ? formatted : `-${formatted}`}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// className: 'column-money'
|
||||
function isMoneyTransaction(record: { type?: number }) {
|
||||
return record.type === 4 || record.type === 3
|
||||
}
|
||||
|
||||
export function buildTransactionsColumns(metals: TransactionMetalColumn[] = []): BaseTableColumn[] {
|
||||
const baseColumns: BaseTableColumn[] = [
|
||||
{
|
||||
title: 'ردیف',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
filterable: false,
|
||||
sortable: false,
|
||||
customRender: (record: any) => {
|
||||
return record.index + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'نوع تراکنش',
|
||||
dataIndex: 'active',
|
||||
key: 'active',
|
||||
filterable: false,
|
||||
sortable: false,
|
||||
customRender: ({record}) => {
|
||||
return record.type === 4 || record.type === 3 ? (
|
||||
<div class="flex justify-center">
|
||||
<CustomTag textColor="#25855A" bgColor="#E3F4E9" class={'font-bold px-6'}>
|
||||
پول
|
||||
</CustomTag>
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex justify-center">
|
||||
{/*<CustomTag textColor="rgb(255 120 0)" bgColor="rgb(255 221 0)">*/}
|
||||
<CustomTag textColor="#ca8a04" bgColor="#fef3c7" class={'font-bold px-6'}>
|
||||
طلا
|
||||
</CustomTag>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'نام مشتری',
|
||||
dataIndex: 'customer.name',
|
||||
key: 'customer.name',
|
||||
type: 'Text'
|
||||
},
|
||||
{
|
||||
title: 'مقدار طلا طی تراکنش (گرم)',
|
||||
dataIndex: 'gold',
|
||||
key: 'gold',
|
||||
type: 'Number',
|
||||
customRender: ({record}) => {
|
||||
return record.gold > 0 ? (
|
||||
<div class="flex justify-center">
|
||||
<div class={'font-bold px-6 text-green'}>{record.gold}</div>
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex justify-center">
|
||||
{/*<CustomTag textColor="rgb(255 120 0)" bgColor="rgb(255 221 0)">*/}
|
||||
<div class={'font-bold px-6 text-red'}>{record.gold}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'مقدار پول طی تراکنش (ریال)',
|
||||
dataIndex: 'cash',
|
||||
key: 'cash',
|
||||
type: 'Number',
|
||||
customRender: ({record}) => {
|
||||
return record.cash > 0 ? (
|
||||
<div class="flex justify-center">
|
||||
<div class={'font-bold px-6 text-green'}>{usePrice(record?.cash ?? 0, true, '')}</div>
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex justify-center">
|
||||
{/*<CustomTag textColor="rgb(255 120 0)" bgColor="rgb(255 221 0)">*/}
|
||||
<div class={'font-bold px-6 text-red'}>{usePrice(record?.cash ?? 0, true, '')}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
/* {
|
||||
title: 'شماره سفارش',
|
||||
dataIndex: 'order_id',
|
||||
key: 'order_id',
|
||||
type: 'Text'
|
||||
},*/
|
||||
/* {
|
||||
title: 'شماره موبایل',
|
||||
dataIndex: 'mobile',
|
||||
key: 'mobile',
|
||||
title: 'کد تراکنش',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
type: 'Number'
|
||||
},*/
|
||||
/* {
|
||||
title: 'نام فروشگاه',
|
||||
dataIndex: 'shop_name',
|
||||
key: 'shop_name',
|
||||
type: 'Text'
|
||||
},*/
|
||||
},
|
||||
{
|
||||
title: 'تاریخ تراکنش',
|
||||
dataIndex: 'created_at',
|
||||
key: 'created_at',
|
||||
type: 'DateTime',
|
||||
customRender: (record: any) => {
|
||||
return toJalaliNoTime(record.record.created_at)
|
||||
}
|
||||
}
|
||||
/*{
|
||||
title: 'نقش',
|
||||
dataIndex: 'user_type_record',
|
||||
key: 'user_type_record',
|
||||
type: 'Select',
|
||||
filterable: false,
|
||||
sortable: false,
|
||||
filterComponentProps: {
|
||||
multiple: true
|
||||
},
|
||||
filterField: 'user_type_obj.id',
|
||||
filterComponent: ReadyUserTypeSelect,
|
||||
/!* customRender: (record: any) => {
|
||||
return record.record.user_type_record?.value
|
||||
}*!/
|
||||
customRender: ({ record }) => {
|
||||
const items = record.is_admin ? (
|
||||
<CustomTag textColor="#25855A" bgColor="#E3F4E9">
|
||||
ادمین
|
||||
title: 'نام تراکنش',
|
||||
dataIndex: 'type_str',
|
||||
key: 'type_str',
|
||||
type: 'Text'
|
||||
},
|
||||
{
|
||||
title: 'علت تراکنش',
|
||||
dataIndex: 'note',
|
||||
key: 'note',
|
||||
type: 'Text'
|
||||
},
|
||||
{
|
||||
title: 'نوع تراکنش',
|
||||
dataIndex: 'active',
|
||||
key: 'active',
|
||||
filterable: false,
|
||||
sortable: false,
|
||||
customRender: ({ record }) => {
|
||||
return isMoneyTransaction(record) ? (
|
||||
<div class="flex justify-center">
|
||||
<CustomTag textColor="#25855A" bgColor="#E3F4E9" class={'font-bold px-6'}>
|
||||
پول
|
||||
</CustomTag>
|
||||
) : (
|
||||
record.user_type_obj.map((item: { title: any }, index: any) => {
|
||||
if (item) {
|
||||
return (
|
||||
<CustomTag textColor="#25855A" bgColor="#E3F4E9">
|
||||
{item?.title}
|
||||
</CustomTag>
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
return <div class="flex justify-center items-center gap-2">{items}</div>
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex justify-center">
|
||||
<CustomTag textColor="#ca8a04" bgColor="#fef3c7" class={'font-bold px-6'}>
|
||||
فلز
|
||||
</CustomTag>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'نوع فلز',
|
||||
dataIndex: 'transaction_metal_label',
|
||||
key: 'transaction_metal_label',
|
||||
filterable: false,
|
||||
sortable: false,
|
||||
customRender: ({ record }) => {
|
||||
if (isMoneyTransaction(record)) {
|
||||
return '-'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'حوزه',
|
||||
dataIndex: 'section',
|
||||
key: 'section'
|
||||
},
|
||||
{
|
||||
title: 'شماره موبایل',
|
||||
dataIndex: 'mobile',
|
||||
type: 'Number',
|
||||
key: 'mobile'
|
||||
},*/
|
||||
/* {
|
||||
title: 'عملیات',
|
||||
dataIndex: 'action',
|
||||
key: 'action',
|
||||
slot: 'action',
|
||||
fixed: 'right',
|
||||
filterable: false
|
||||
}*/
|
||||
]
|
||||
return (
|
||||
<div class="flex justify-center">
|
||||
<CustomTag textColor="#ca8a04" bgColor="#fef3c7" class={'font-bold px-6'}>
|
||||
{record.transaction_metal_label ?? metalLabel.goldUnit()}
|
||||
</CustomTag>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'نام مشتری',
|
||||
dataIndex: 'customer.name',
|
||||
key: 'customer.name',
|
||||
type: 'Text'
|
||||
}
|
||||
]
|
||||
|
||||
const metalColumns: BaseTableColumn[] =
|
||||
metals.length > 0
|
||||
? metals.map((metal) => ({
|
||||
title: transactionMetalAmountTitle(metal.metal_id, metal.label),
|
||||
dataIndex: `metal_gold_${metal.metal_id}`,
|
||||
key: `metal_${metal.metal_id}`,
|
||||
type: 'Number',
|
||||
customRender: ({ record }) => renderSignedMetalCell(metalCellValue(record, metal.metal_id), metal.metal_id)
|
||||
}))
|
||||
: [
|
||||
{
|
||||
title: metalLabel.goldInTransaction(),
|
||||
dataIndex: 'gold',
|
||||
key: 'gold',
|
||||
type: 'Number',
|
||||
customRender: ({ record }) => renderSignedMetalCell(Number(record.gold ?? 0), 1)
|
||||
}
|
||||
]
|
||||
|
||||
return [
|
||||
...baseColumns,
|
||||
...metalColumns,
|
||||
{
|
||||
title: 'مقدار پول طی تراکنش (ریال)',
|
||||
dataIndex: 'cash',
|
||||
key: 'cash',
|
||||
type: 'Number',
|
||||
customRender: ({ record }) => {
|
||||
return record.cash > 0 ? (
|
||||
<div class="flex justify-center">
|
||||
<div class={'font-bold px-6 text-green'}>{usePrice(record?.cash ?? 0, true, '')}</div>
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex justify-center">
|
||||
<div class={'font-bold px-6 text-red'}>{usePrice(record?.cash ?? 0, true, '')}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'تاریخ تراکنش',
|
||||
dataIndex: 'created_at',
|
||||
key: 'created_at',
|
||||
type: 'DateTime',
|
||||
customRender: (record: any) => {
|
||||
return toJalaliNoTime(record.record.created_at)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export function getTransactionsColumns(): BaseTableColumn[] {
|
||||
return buildTransactionsColumns()
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ import type { Item } from '@/model/Item'
|
||||
import type { Customer } from '@/model/customer'
|
||||
import { createCustomer, deleteCustomer, updateCustomer } from '@/api/customer'
|
||||
import type { Transaction } from '@/model/transaction'
|
||||
import { metalLabel } from '@/utils/adminMetalLabels'
|
||||
|
||||
//loading
|
||||
const loading = ref<boolean>(false)
|
||||
@@ -127,7 +128,7 @@ let infoParams = reactive<Info>({})
|
||||
|
||||
function info(val: Transaction) {
|
||||
infoParams.name = val.customer.name
|
||||
infoParams.type = val.transaction_type === '1' ? 'نقدی' : 'طلا'
|
||||
infoParams.type = val.transaction_type === '1' ? 'نقدی' : metalLabel.goldUnit()
|
||||
infoParams.date = toJalaliNoTime(val.created_at)
|
||||
infoParams.time = toTime(val.created_at)
|
||||
infoParams.itemsTitle = 'اطلاعات کاربری'
|
||||
|
||||
Reference in New Issue
Block a user