wallet fix 2
This commit is contained in:
Vendored
+1
@@ -83,6 +83,7 @@ declare module '@vue/runtime-core' {
|
|||||||
CustomTag: typeof import('./src/components/CustomTag.vue')['default']
|
CustomTag: typeof import('./src/components/CustomTag.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
TahesabRetryModal: typeof import('./src/components/TahesabRetryModal.vue')['default']
|
||||||
ThemeMenuSection: typeof import('./src/core/components/ThemeMenuSection.vue')['default']
|
ThemeMenuSection: typeof import('./src/core/components/ThemeMenuSection.vue')['default']
|
||||||
ThemeToggle: typeof import('./src/core/components/ThemeToggle.vue')['default']
|
ThemeToggle: typeof import('./src/core/components/ThemeToggle.vue')['default']
|
||||||
UploadPic: typeof import('./src/components/UploadPic.vue')['default']
|
UploadPic: typeof import('./src/components/UploadPic.vue')['default']
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import useAxios from '@core/utils/useAxios'
|
||||||
|
import type { TableInput } from '@core/type/baseTable'
|
||||||
|
|
||||||
|
export interface TahesabRecord {
|
||||||
|
id: number
|
||||||
|
customer_id?: number
|
||||||
|
amount?: number
|
||||||
|
desc?: string
|
||||||
|
type?: string
|
||||||
|
sync_status?: 'pending' | 'success' | 'failed'
|
||||||
|
sync_log?: string | null
|
||||||
|
tahesab_id?: string | null
|
||||||
|
data?: string | null
|
||||||
|
res?: string | null
|
||||||
|
created_at?: string
|
||||||
|
customer?: {
|
||||||
|
id?: number
|
||||||
|
name?: string
|
||||||
|
mobile?: string
|
||||||
|
moshtari_code?: string | number | null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getTahesabTable = async (params: TableInput) =>
|
||||||
|
await useAxios.post<TahesabRecord[]>('/admin/tahesab/table', params)
|
||||||
|
|
||||||
|
export const getTahesabDetail = async (id: number) =>
|
||||||
|
await useAxios.get<TahesabRecord>(`/admin/tahesab/${id}`)
|
||||||
|
|
||||||
|
export const retryTahesabSanad = async (id: number) =>
|
||||||
|
await useAxios.post<{ ok: boolean; message: string; tahesab?: TahesabRecord }>(`/admin/tahesab/${id}/retry`)
|
||||||
|
|
||||||
|
export const registerCustomerInTahesab = async (customerId: number) =>
|
||||||
|
await useAxios.post<{ ok: boolean; message: string; moshtari_code?: string | number }>(
|
||||||
|
`/admin/customer/${customerId}/tahesab/register`
|
||||||
|
)
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<BasicModal
|
||||||
|
v-model:visible="visible"
|
||||||
|
:title="title"
|
||||||
|
:ok-text="confirmText"
|
||||||
|
:loading="loading"
|
||||||
|
width="32rem"
|
||||||
|
@ok="confirm"
|
||||||
|
@close="visible = false"
|
||||||
|
>
|
||||||
|
<div class="space-y-3 text-sm">
|
||||||
|
<div v-for="item in items" :key="item.label" class="flex justify-between gap-3 border-b border-gray-100 pb-2">
|
||||||
|
<span class="text-gray-500">{{ item.label }}</span>
|
||||||
|
<span class="text-left break-all">{{ item.value ?? '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="logText" class="rounded-lg bg-red-50 p-3 text-red-700 whitespace-pre-wrap">{{ logText }}</div>
|
||||||
|
</div>
|
||||||
|
</BasicModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from 'vue'
|
||||||
|
import BasicModal from '@/components/BasicModal.vue'
|
||||||
|
import { message } from 'ant-design-vue/es'
|
||||||
|
import { getTahesabDetail, retryTahesabSanad, registerCustomerInTahesab, type TahesabRecord } from '@/api/tahesab'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: boolean
|
||||||
|
mode: 'retry-sanad' | 'register-customer'
|
||||||
|
tahesabId?: number
|
||||||
|
customerId?: number
|
||||||
|
customerName?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:modelValue', value: boolean): void
|
||||||
|
(e: 'success'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const detail = ref<TahesabRecord | null>(null)
|
||||||
|
|
||||||
|
const visible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (value: boolean) => emit('update:modelValue', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const title = computed(() =>
|
||||||
|
props.mode === 'register-customer' ? 'ثبت مشتری در تهحساب' : 'ارسال مجدد سند به تهحساب'
|
||||||
|
)
|
||||||
|
|
||||||
|
const confirmText = computed(() => (props.mode === 'register-customer' ? 'ثبت در تهحساب' : 'ارسال به تهحساب'))
|
||||||
|
|
||||||
|
const logText = computed(() => detail.value?.sync_log || '')
|
||||||
|
|
||||||
|
const items = computed(() => {
|
||||||
|
if (props.mode === 'register-customer') {
|
||||||
|
return [
|
||||||
|
{ label: 'نام مشتری', value: props.customerName || detail.value?.customer?.name },
|
||||||
|
{ label: 'شناسه مشتری', value: props.customerId || detail.value?.customer_id },
|
||||||
|
{ label: 'کد تهحساب', value: detail.value?.customer?.moshtari_code }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{ label: 'شناسه سند', value: detail.value?.id },
|
||||||
|
{ label: 'مشتری', value: detail.value?.customer?.name },
|
||||||
|
{ label: 'موبایل', value: detail.value?.customer?.mobile },
|
||||||
|
{ label: 'نوع', value: detail.value?.type },
|
||||||
|
{ label: 'مقدار', value: detail.value?.amount },
|
||||||
|
{ label: 'شرح', value: detail.value?.desc },
|
||||||
|
{ label: 'وضعیت', value: statusLabel(detail.value?.sync_status) },
|
||||||
|
{ label: 'کد تهحساب', value: detail.value?.tahesab_id }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
function statusLabel(status?: string) {
|
||||||
|
if (status === 'success') return 'موفق'
|
||||||
|
if (status === 'failed') return 'ناموفق'
|
||||||
|
return 'در انتظار'
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [props.modelValue, props.tahesabId] as const,
|
||||||
|
async ([open, id]) => {
|
||||||
|
if (!open || props.mode !== 'retry-sanad' || !id) return
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
detail.value = await getTahesabDetail(id)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
async function confirm() {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
if (props.mode === 'register-customer' && props.customerId) {
|
||||||
|
const result = await registerCustomerInTahesab(props.customerId)
|
||||||
|
if (!result.ok) {
|
||||||
|
message.error(result.message || 'ثبت مشتری ناموفق بود')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
message.success(result.message || 'مشتری در تهحساب ثبت شد')
|
||||||
|
} else if (props.mode === 'retry-sanad' && props.tahesabId) {
|
||||||
|
const result = await retryTahesabSanad(props.tahesabId)
|
||||||
|
if (!result.ok) {
|
||||||
|
message.error(result.message || 'ارسال مجدد ناموفق بود')
|
||||||
|
detail.value = result.tahesab || detail.value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
message.success(result.message || 'سند با موفقیت ثبت شد')
|
||||||
|
}
|
||||||
|
visible.value = false
|
||||||
|
emit('success')
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -36,5 +36,6 @@ export interface Customer {
|
|||||||
trade_active: boolean
|
trade_active: boolean
|
||||||
type_str: string
|
type_str: string
|
||||||
gold: number
|
gold: number
|
||||||
|
moshtari_code?: string | number | null
|
||||||
// print_name: string
|
// print_name: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,24 @@
|
|||||||
<BaseTable v-bind="tblProps" @register="submit" ref="tbl">
|
<BaseTable v-bind="tblProps" @register="submit" ref="tbl">
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
<div class="flex justify-center gap-2">
|
<div class="flex justify-center gap-2">
|
||||||
|
<a-tooltip
|
||||||
|
v-if="showTahesab && record.tahesab_record_id"
|
||||||
|
placement="bottom"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="openTahesabDetail(record)"
|
||||||
|
>
|
||||||
|
<template #title><span>جزئیات تهحساب</span></template>
|
||||||
|
<Icon icon="vuesax-linear:document-text" color="#10913A" />
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip
|
||||||
|
v-if="showTahesab && record.tahesab_failed_id"
|
||||||
|
placement="bottom"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="openTahesabRetry(record)"
|
||||||
|
>
|
||||||
|
<template #title><span>ارسال به تهحساب</span></template>
|
||||||
|
<Icon icon="vuesax-linear:refresh-circle" color="#CA8A04" />
|
||||||
|
</a-tooltip>
|
||||||
<a-tooltip placement="bottom" class="cursor-pointer" @click="emits('info', record)">
|
<a-tooltip placement="bottom" class="cursor-pointer" @click="emits('info', record)">
|
||||||
<template #title><span>برداشت و واریز</span></template>
|
<template #title><span>برداشت و واریز</span></template>
|
||||||
<Icon icon="vuesax-linear:stickynote" color="#10913A" />
|
<Icon icon="vuesax-linear:stickynote" color="#10913A" />
|
||||||
@@ -25,22 +43,53 @@
|
|||||||
@orders="emits('orders', $event)"
|
@orders="emits('orders', $event)"
|
||||||
/>
|
/>
|
||||||
</BasicShowContext>
|
</BasicShowContext>
|
||||||
|
|
||||||
|
<TahesabRetryModal
|
||||||
|
v-if="showTahesab"
|
||||||
|
v-model="tahesabRetryVisible"
|
||||||
|
mode="retry-sanad"
|
||||||
|
:tahesab-id="selectedTahesabId"
|
||||||
|
@success="fetch"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<BasicModal
|
||||||
|
v-if="showTahesab"
|
||||||
|
v-model:visible="tahesabDetailVisible" title="جزئیات سند تهحساب" width="36rem" :footer="null">
|
||||||
|
<div class="space-y-2 text-sm">
|
||||||
|
<div v-for="item in tahesabDetailItems" :key="item.label" class="flex justify-between gap-3 border-b border-gray-100 py-2">
|
||||||
|
<span class="text-gray-500">{{ item.label }}</span>
|
||||||
|
<span class="break-all text-left">{{ item.value ?? '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="tahesabDetail?.sync_log" class="rounded-lg bg-red-50 p-3 text-red-700 whitespace-pre-wrap">
|
||||||
|
{{ tahesabDetail.sync_log }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BasicModal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { getTotalAccountingTable } from '@/api/accounting'
|
import { getTotalAccountingTable } from '@/api/accounting'
|
||||||
|
import { getTahesabDetail, type TahesabRecord } from '@/api/tahesab'
|
||||||
import { getAccountingColumns } from '@/pages/menuPages/accounting/hooks/accountingColumns'
|
import { getAccountingColumns } from '@/pages/menuPages/accounting/hooks/accountingColumns'
|
||||||
import AccountingMobileCardList from '@/pages/menuPages/accounting/components/AccountingMobileCardList.vue'
|
import AccountingMobileCardList from '@/pages/menuPages/accounting/components/AccountingMobileCardList.vue'
|
||||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||||
import useBaseTable from '@core/components/BaseTable/hooks/useBaseTable'
|
import useBaseTable from '@core/components/BaseTable/hooks/useBaseTable'
|
||||||
import type { TableInput } from '@core/type/baseTable'
|
import type { TableInput } from '@core/type/baseTable'
|
||||||
import { isMobile } from '@core/utils/is'
|
import { isMobile } from '@core/utils/is'
|
||||||
|
import TahesabRetryModal from '@/components/TahesabRetryModal.vue'
|
||||||
|
import BasicModal from '@/components/BasicModal.vue'
|
||||||
|
|
||||||
defineProps<{
|
const props = withDefaults(
|
||||||
customerId?: number
|
defineProps<{
|
||||||
}>()
|
customerId?: number
|
||||||
|
showTahesab?: boolean
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
showTahesab: false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
(e: 'info', record: unknown): void
|
(e: 'info', record: unknown): void
|
||||||
@@ -49,12 +98,45 @@ const emits = defineEmits<{
|
|||||||
|
|
||||||
const [submit, reload] = useBaseTable()
|
const [submit, reload] = useBaseTable()
|
||||||
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
|
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
|
||||||
|
const tahesabRetryVisible = ref(false)
|
||||||
|
const tahesabDetailVisible = ref(false)
|
||||||
|
const selectedTahesabId = ref<number>()
|
||||||
|
const tahesabDetail = ref<TahesabRecord | null>(null)
|
||||||
|
|
||||||
|
const tahesabDetailItems = computed(() => {
|
||||||
|
const row = tahesabDetail.value
|
||||||
|
if (!row) return []
|
||||||
|
return [
|
||||||
|
{ label: 'شناسه', value: row.id },
|
||||||
|
{ label: 'مشتری', value: row.customer?.name },
|
||||||
|
{ label: 'نوع', value: row.type },
|
||||||
|
{ label: 'مقدار', value: row.amount },
|
||||||
|
{ label: 'شرح', value: row.desc },
|
||||||
|
{ label: 'وضعیت', value: tahesabStatusLabel(row) },
|
||||||
|
{ label: 'کد تهحساب', value: row.tahesab_id }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
function tahesabStatusLabel(row?: TahesabRecord | null) {
|
||||||
|
if (!row) return '-'
|
||||||
|
if (row.tahesab_id) return 'موفق'
|
||||||
|
if (row.sync_status === 'failed') return 'ناموفق'
|
||||||
|
if (row.sync_status === 'success') return 'موفق'
|
||||||
|
return 'در انتظار'
|
||||||
|
}
|
||||||
|
|
||||||
const tblProps = ref({
|
const tblProps = ref({
|
||||||
columns: getAccountingColumns(),
|
columns: getAccountingColumns(props.showTahesab),
|
||||||
api: (params: TableInput) => getTotalAccountingTable(params)
|
api: (params: TableInput) => getTotalAccountingTable(params)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.showTahesab,
|
||||||
|
(enabled) => {
|
||||||
|
tblProps.value.columns = getAccountingColumns(enabled)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
if (isMobile.value) {
|
if (isMobile.value) {
|
||||||
await mobileListRef.value?.fetch?.()
|
await mobileListRef.value?.fetch?.()
|
||||||
@@ -63,5 +145,22 @@ async function fetch() {
|
|||||||
await reload()
|
await reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openTahesabRetry(record: { tahesab_failed_id?: number }) {
|
||||||
|
if (!record.tahesab_failed_id) return
|
||||||
|
selectedTahesabId.value = record.tahesab_failed_id
|
||||||
|
tahesabRetryVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openTahesabDetail(record: { tahesab_record_id?: number }) {
|
||||||
|
if (!record.tahesab_record_id) return
|
||||||
|
selectedTahesabId.value = record.tahesab_record_id
|
||||||
|
try {
|
||||||
|
tahesabDetail.value = await getTahesabDetail(record.tahesab_record_id)
|
||||||
|
tahesabDetailVisible.value = true
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({ fetch })
|
defineExpose({ fetch })
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
<template>
|
||||||
|
<div class="min-w-0 w-full max-w-full overflow-x-hidden">
|
||||||
|
<BasicShowContext title="اسناد تهحساب">
|
||||||
|
<div v-if="!isMobile" class="min-w-0 w-full max-w-full overflow-x-auto">
|
||||||
|
<BaseTable v-bind="tblProps" @register="submit" ref="tbl">
|
||||||
|
<template #action="{ record }">
|
||||||
|
<div class="flex justify-center gap-2">
|
||||||
|
<a-tooltip placement="bottom" class="cursor-pointer" @click="openDetail(record)">
|
||||||
|
<template #title><span>جزئیات</span></template>
|
||||||
|
<Icon icon="vuesax-linear:stickynote" color="#10913A" />
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip
|
||||||
|
v-if="canRetry(record)"
|
||||||
|
placement="bottom"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="openRetry(record)"
|
||||||
|
>
|
||||||
|
<template #title><span>ارسال به تهحساب</span></template>
|
||||||
|
<Icon icon="vuesax-linear:refresh-circle" color="#CA8A04" />
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BaseTable>
|
||||||
|
</div>
|
||||||
|
</BasicShowContext>
|
||||||
|
|
||||||
|
<BasicModal v-model:visible="detailVisible" title="جزئیات سند تهحساب" width="36rem" :footer="null">
|
||||||
|
<div class="space-y-2 text-sm">
|
||||||
|
<div v-for="item in detailItems" :key="item.label" class="flex justify-between gap-3 border-b border-gray-100 py-2">
|
||||||
|
<span class="text-gray-500">{{ item.label }}</span>
|
||||||
|
<span class="break-all text-left">{{ item.value ?? '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="selected?.sync_log" class="rounded-lg bg-red-50 p-3 text-red-700 whitespace-pre-wrap">
|
||||||
|
{{ selected.sync_log }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BasicModal>
|
||||||
|
|
||||||
|
<TahesabRetryModal
|
||||||
|
v-model="retryVisible"
|
||||||
|
mode="retry-sanad"
|
||||||
|
:tahesab-id="selected?.id"
|
||||||
|
@success="fetch"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import useBaseTable from '@core/components/BaseTable/hooks/useBaseTable'
|
||||||
|
import type { TableInput } from '@core/type/baseTable'
|
||||||
|
import { getTahesabTable, type TahesabRecord } from '@/api/tahesab'
|
||||||
|
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||||
|
import { isMobile } from '@core/utils/is'
|
||||||
|
import BasicModal from '@/components/BasicModal.vue'
|
||||||
|
import TahesabRetryModal from '@/components/TahesabRetryModal.vue'
|
||||||
|
import { toJalali } from '@core/utils/useDataTime'
|
||||||
|
|
||||||
|
const [submit, reload] = useBaseTable()
|
||||||
|
const detailVisible = ref(false)
|
||||||
|
const retryVisible = ref(false)
|
||||||
|
const selected = ref<TahesabRecord | null>(null)
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ title: 'ردیف', dataIndex: 'id', key: 'id', filterable: false, sortable: false, customRender: (r: any) => r.index + 1 },
|
||||||
|
{ title: 'مشتری', dataIndex: 'customer.name', key: 'customer.name', type: 'Text' },
|
||||||
|
{ title: 'نوع', dataIndex: 'type', key: 'type', type: 'Text' },
|
||||||
|
{ title: 'مقدار', dataIndex: 'amount', key: 'amount', type: 'Number' },
|
||||||
|
{ title: 'شرح', dataIndex: 'desc', key: 'desc', type: 'Text' },
|
||||||
|
{
|
||||||
|
title: 'وضعیت',
|
||||||
|
dataIndex: 'sync_status',
|
||||||
|
key: 'sync_status',
|
||||||
|
type: 'Text',
|
||||||
|
customRender: (r: any) => statusLabel(r.record.sync_status, r.record.tahesab_id)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'زمان',
|
||||||
|
dataIndex: 'created_at',
|
||||||
|
key: 'created_at',
|
||||||
|
type: 'Text',
|
||||||
|
customRender: (r: any) => toJalali(r.record.created_at)
|
||||||
|
},
|
||||||
|
{ title: 'عملیات', dataIndex: 'action', key: 'action', slot: 'action', filterable: false }
|
||||||
|
]
|
||||||
|
|
||||||
|
const tblProps = ref({
|
||||||
|
columns,
|
||||||
|
api: (params: TableInput) => getTahesabTable(params)
|
||||||
|
})
|
||||||
|
|
||||||
|
const detailItems = computed(() => {
|
||||||
|
const row = selected.value
|
||||||
|
if (!row) return []
|
||||||
|
return [
|
||||||
|
{ label: 'شناسه', value: row.id },
|
||||||
|
{ label: 'مشتری', value: row.customer?.name },
|
||||||
|
{ label: 'موبایل', value: row.customer?.mobile },
|
||||||
|
{ label: 'نوع', value: row.type },
|
||||||
|
{ label: 'مقدار', value: row.amount },
|
||||||
|
{ label: 'شرح', value: row.desc },
|
||||||
|
{ label: 'وضعیت', value: statusLabel(row.sync_status, row.tahesab_id) },
|
||||||
|
{ label: 'کد تهحساب', value: row.tahesab_id },
|
||||||
|
{ label: 'پاسخ API', value: row.res }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
function statusLabel(status?: string, tahesabId?: string | null) {
|
||||||
|
if (tahesabId) return 'موفق'
|
||||||
|
if (status === 'failed') return 'ناموفق'
|
||||||
|
if (status === 'success') return 'موفق'
|
||||||
|
return 'در انتظار'
|
||||||
|
}
|
||||||
|
|
||||||
|
function canRetry(record: TahesabRecord) {
|
||||||
|
return !record.tahesab_id || record.sync_status === 'failed'
|
||||||
|
}
|
||||||
|
|
||||||
|
function openDetail(record: TahesabRecord) {
|
||||||
|
selected.value = record
|
||||||
|
detailVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function openRetry(record: TahesabRecord) {
|
||||||
|
selected.value = record
|
||||||
|
retryVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetch() {
|
||||||
|
await reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ fetch })
|
||||||
|
</script>
|
||||||
@@ -22,7 +22,7 @@ const filteredDocTypes: FilterSelect = docTypes?.map((x: DocItem) => {
|
|||||||
}
|
}
|
||||||
})*/
|
})*/
|
||||||
|
|
||||||
export function getAccountingColumns(): BaseTableColumn[] {
|
export function getAccountingColumns(showTahesab = false): BaseTableColumn[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: 'ردیف',
|
title: 'ردیف',
|
||||||
@@ -76,6 +76,25 @@ export function getAccountingColumns(): BaseTableColumn[] {
|
|||||||
key: 'note',
|
key: 'note',
|
||||||
type: 'Text',
|
type: 'Text',
|
||||||
},
|
},
|
||||||
|
...(showTahesab
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
title: 'تهحساب',
|
||||||
|
dataIndex: 'tahesab_sync_status',
|
||||||
|
key: 'tahesab_sync_status',
|
||||||
|
type: 'Text',
|
||||||
|
filterable: false,
|
||||||
|
customRender: (record: any) => {
|
||||||
|
const row = record.record
|
||||||
|
if (!row.tahesab_record_id && !row.tahesab_sync_status) return '-'
|
||||||
|
if (row.tahesab_failed_id) return 'ناموفق'
|
||||||
|
if (row.tahesab_sync_status === 'success') return 'موفق'
|
||||||
|
if (row.tahesab_sync_status === 'pending') return 'در انتظار'
|
||||||
|
return row.tahesab_sync_status ?? '-'
|
||||||
|
}
|
||||||
|
} as BaseTableColumn
|
||||||
|
]
|
||||||
|
: []),
|
||||||
{
|
{
|
||||||
title: 'عملیات',
|
title: 'عملیات',
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<BasicMainCard>
|
<BasicMainCard>
|
||||||
<div class="flex h-full w-full min-w-0 max-w-full overflow-x-hidden">
|
<div class="flex h-full w-full min-w-0 max-w-full flex-col overflow-x-hidden">
|
||||||
<tbl ref="table" class="h-full w-full min-w-0" @info="onAccountingWithdraw" @orders="onAccountingOrders" />
|
<ATabs v-if="tahesabEnabled" v-model:activeKey="activeTab" class="mb-3 shrink-0">
|
||||||
|
<ATabPane key="reports" tab="گزارشات" />
|
||||||
<!-- <BasicMenu :menu="menu" width="13rem" @onChange="tabSelected" />
|
<ATabPane key="tahesab" tab="اسناد تهحساب" />
|
||||||
<component :is="selectedComponent" class="mr-5" />-->
|
</ATabs>
|
||||||
<!-- <BasicShowContext title="پروژه ها"> <Search /> </BasicShowContext>-->
|
<tbl
|
||||||
|
v-if="!tahesabEnabled || activeTab === 'reports'"
|
||||||
|
ref="table"
|
||||||
|
class="min-h-0 flex-1"
|
||||||
|
:show-tahesab="tahesabEnabled"
|
||||||
|
@info="onAccountingWithdraw"
|
||||||
|
@orders="onAccountingOrders"
|
||||||
|
/>
|
||||||
|
<tahesabTbl v-else-if="tahesabEnabled" ref="tahesabTable" class="min-h-0 flex-1" />
|
||||||
</div>
|
</div>
|
||||||
</BasicMainCard>
|
</BasicMainCard>
|
||||||
<BasicModal
|
<BasicModal
|
||||||
@@ -126,6 +134,7 @@ import { inputLenRules, inputRules, inputRulesNumber } from '@/utils/inputRules'
|
|||||||
import { useStaticApiListsStore } from '@/store/staticApisStore'
|
import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import tbl from './components/table.vue'
|
import tbl from './components/table.vue'
|
||||||
|
import tahesabTbl from './components/tahesabTable.vue'
|
||||||
import type { FormInstance } from 'ant-design-vue'
|
import type { FormInstance } from 'ant-design-vue'
|
||||||
import BasicInfoModal from '@/components/BasicInfoModal/index.vue'
|
import BasicInfoModal from '@/components/BasicInfoModal/index.vue'
|
||||||
import { message } from 'ant-design-vue/es'
|
import { message } from 'ant-design-vue/es'
|
||||||
@@ -144,9 +153,12 @@ import type { last } from '@/model/price'
|
|||||||
import { createOrder } from '@/api/order'
|
import { createOrder } from '@/api/order'
|
||||||
import { getCashBalance, getGoldBalance } from '@/components/mobile/utils/wallet'
|
import { getCashBalance, getGoldBalance } from '@/components/mobile/utils/wallet'
|
||||||
import { metalLabel } from '@/utils/adminMetalLabels'
|
import { metalLabel } from '@/utils/adminMetalLabels'
|
||||||
|
import { initTahesabSettingFromApi, tahesabEnabledSetting } from '@/utils/config'
|
||||||
|
|
||||||
//loading
|
//loading
|
||||||
const loading = ref<boolean>(false)
|
const loading = ref<boolean>(false)
|
||||||
|
const activeTab = ref<'reports' | 'tahesab'>('reports')
|
||||||
|
const tahesabEnabled = tahesabEnabledSetting
|
||||||
|
|
||||||
//define store
|
//define store
|
||||||
const store = useStaticApiListsStore()
|
const store = useStaticApiListsStore()
|
||||||
@@ -171,6 +183,7 @@ async function getCustomers() {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getCustomers()
|
getCustomers()
|
||||||
|
void initTahesabSettingFromApi()
|
||||||
})
|
})
|
||||||
|
|
||||||
//form
|
//form
|
||||||
|
|||||||
@@ -57,6 +57,15 @@
|
|||||||
<template #title><span>{{ metalLabel.goldWalletCharge() }}</span></template>
|
<template #title><span>{{ metalLabel.goldWalletCharge() }}</span></template>
|
||||||
<Icon icon="vuesax-linear:wallet-money" color="#ea580c" />
|
<Icon icon="vuesax-linear:wallet-money" color="#ea580c" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
<a-tooltip
|
||||||
|
v-if="tahesabEnabled && !record.moshtari_code"
|
||||||
|
placement="bottom"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="openTahesabRegister(record)"
|
||||||
|
>
|
||||||
|
<template #title><span>ثبت در تهحساب</span></template>
|
||||||
|
<Icon icon="vuesax-linear:refresh-circle" color="#CA8A04" />
|
||||||
|
</a-tooltip>
|
||||||
<a-tooltip placement="bottom" class="cursor-pointer" @click="emits('info', record)">
|
<a-tooltip placement="bottom" class="cursor-pointer" @click="emits('info', record)">
|
||||||
<template #title><span>مشخصات</span></template>
|
<template #title><span>مشخصات</span></template>
|
||||||
<Icon icon="vuesax-linear:stickynote" color="#10913A" />
|
<Icon icon="vuesax-linear:stickynote" color="#10913A" />
|
||||||
@@ -130,6 +139,15 @@
|
|||||||
<BasicInfoItem title="شماره ملی" :value="confirmInfo?.n_code" />
|
<BasicInfoItem title="شماره ملی" :value="confirmInfo?.n_code" />
|
||||||
</div>
|
</div>
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
|
|
||||||
|
<TahesabRetryModal
|
||||||
|
v-if="tahesabEnabled"
|
||||||
|
v-model="tahesabRegisterVisible"
|
||||||
|
mode="register-customer"
|
||||||
|
:customer-id="tahesabCustomer?.id"
|
||||||
|
:customer-name="tahesabCustomer?.name"
|
||||||
|
@success="fetch"
|
||||||
|
/>
|
||||||
</BasicShowContext>
|
</BasicShowContext>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -154,6 +172,8 @@ import type { Customer } from '@/model/customer'
|
|||||||
import { MODAL_ABOVE_ACTION_SHEET_Z_INDEX } from '@/constants/overlayZIndex'
|
import { MODAL_ABOVE_ACTION_SHEET_Z_INDEX } from '@/constants/overlayZIndex'
|
||||||
import { isMobile } from '@core/utils/is'
|
import { isMobile } from '@core/utils/is'
|
||||||
import { metalLabel } from '@/utils/adminMetalLabels'
|
import { metalLabel } from '@/utils/adminMetalLabels'
|
||||||
|
import TahesabRetryModal from '@/components/TahesabRetryModal.vue'
|
||||||
|
import { tahesabEnabledSetting, initTahesabSettingFromApi } from '@/utils/config'
|
||||||
|
|
||||||
const [submit, reload] = useBaseTable()
|
const [submit, reload] = useBaseTable()
|
||||||
const emits = defineEmits(['delete', 'edit', 'add', 'info', 'chargeMoney', 'chargeGold'])
|
const emits = defineEmits(['delete', 'edit', 'add', 'info', 'chargeMoney', 'chargeGold'])
|
||||||
@@ -161,6 +181,9 @@ const emits = defineEmits(['delete', 'edit', 'add', 'info', 'chargeMoney', 'char
|
|||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const confirmVisible = ref(false)
|
const confirmVisible = ref(false)
|
||||||
const confirmInfo = ref<Customer>()
|
const confirmInfo = ref<Customer>()
|
||||||
|
const tahesabRegisterVisible = ref(false)
|
||||||
|
const tahesabCustomer = ref<Customer>()
|
||||||
|
const tahesabEnabled = tahesabEnabledSetting
|
||||||
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
|
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
|
||||||
|
|
||||||
const tblProps = ref<any>({
|
const tblProps = ref<any>({
|
||||||
@@ -179,6 +202,10 @@ const fetch = async () => {
|
|||||||
|
|
||||||
defineExpose({ fetch })
|
defineExpose({ fetch })
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
void initTahesabSettingFromApi()
|
||||||
|
})
|
||||||
|
|
||||||
async function changeCustomerActivationFunction(id: number) {
|
async function changeCustomerActivationFunction(id: number) {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -197,6 +224,11 @@ function openConfirmUser(user: Customer) {
|
|||||||
confirmVisible.value = true
|
confirmVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openTahesabRegister(user: Customer) {
|
||||||
|
tahesabCustomer.value = user
|
||||||
|
tahesabRegisterVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
function handleArchive(customer: Customer) {
|
function handleArchive(customer: Customer) {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: 'آیا مشتری را بایگانی می کنید؟',
|
title: 'آیا مشتری را بایگانی می کنید؟',
|
||||||
|
|||||||
@@ -66,6 +66,14 @@
|
|||||||
@click="emits('weight', record)"
|
@click="emits('weight', record)"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
<a-tooltip
|
||||||
|
v-if="tahesabEnabled && record.tahesab_failed_id"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="openTahesabRetry(record)"
|
||||||
|
>
|
||||||
|
<template #title><span>ارسال به تهحساب</span></template>
|
||||||
|
<Icon icon="vuesax-linear:refresh-circle" color="#CA8A04" />
|
||||||
|
</a-tooltip>
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -80,6 +88,14 @@
|
|||||||
@weight="(row) => emits('weight', row)"
|
@weight="(row) => emits('weight', row)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<TahesabRetryModal
|
||||||
|
v-if="tahesabEnabled"
|
||||||
|
v-model="tahesabRetryVisible"
|
||||||
|
mode="retry-sanad"
|
||||||
|
:tahesab-id="selectedTahesabId"
|
||||||
|
@success="fetch"
|
||||||
|
/>
|
||||||
</BasicShowContext>
|
</BasicShowContext>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -98,6 +114,8 @@ import {getWithdrawTable, updateSts} from '@/api/wallet'
|
|||||||
import WithdrawMobileCardList from './WithdrawMobileCardList.vue'
|
import WithdrawMobileCardList from './WithdrawMobileCardList.vue'
|
||||||
import { isMobile } from '@core/utils/is'
|
import { isMobile } from '@core/utils/is'
|
||||||
import type { WithdrawFlowType } from '../types'
|
import type { WithdrawFlowType } from '../types'
|
||||||
|
import TahesabRetryModal from '@/components/TahesabRetryModal.vue'
|
||||||
|
import { initTahesabSettingFromApi, tahesabEnabledSetting } from '@/utils/config'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -110,6 +128,9 @@ const props = withDefaults(
|
|||||||
|
|
||||||
const [submit, reload] = useBaseTable()
|
const [submit, reload] = useBaseTable()
|
||||||
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
|
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
|
||||||
|
const tahesabRetryVisible = ref(false)
|
||||||
|
const selectedTahesabId = ref<number>()
|
||||||
|
const tahesabEnabled = tahesabEnabledSetting
|
||||||
/*const select = (val) => {
|
/*const select = (val) => {
|
||||||
val.sts === 1 ? return ['1'] : ['2']
|
val.sts === 1 ? return ['1'] : ['2']
|
||||||
}*/
|
}*/
|
||||||
@@ -166,6 +187,12 @@ async function changeCustomerActivationFunction(id: number) {
|
|||||||
async function fetch() {
|
async function fetch() {
|
||||||
await Promise.allSettled([reload(), mobileListRef.value?.fetch?.() as Promise<void>])
|
await Promise.allSettled([reload(), mobileListRef.value?.fetch?.() as Promise<void>])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openTahesabRetry(record: { tahesab_failed_id?: number }) {
|
||||||
|
if (!record.tahesab_failed_id) return
|
||||||
|
selectedTahesabId.value = record.tahesab_failed_id
|
||||||
|
tahesabRetryVisible.value = true
|
||||||
|
}
|
||||||
// const spinTable = (val: boolean) => {
|
// const spinTable = (val: boolean) => {
|
||||||
// // console.log('sss')
|
// // console.log('sss')
|
||||||
// table?.value?.loading.value = val
|
// table?.value?.loading.value = val
|
||||||
@@ -175,6 +202,10 @@ defineExpose({
|
|||||||
getExportParams: () => ({ ...lastTableParams.value, flow_type: props.flowType })
|
getExportParams: () => ({ ...lastTableParams.value, flow_type: props.flowType })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
void initTahesabSettingFromApi()
|
||||||
|
})
|
||||||
|
|
||||||
import { status } from '@/pages/menuPages/withdraw/information/hooks/status'
|
import { status } from '@/pages/menuPages/withdraw/information/hooks/status'
|
||||||
import {toNumber} from "lodash";
|
import {toNumber} from "lodash";
|
||||||
const withdrawId = ref(null)
|
const withdrawId = ref(null)
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ let settingsBootstrapped = false
|
|||||||
/** reactive — برای فیلتر منوی «بنرها» در پیکربندی */
|
/** reactive — برای فیلتر منوی «بنرها» در پیکربندی */
|
||||||
export const bannerEnabledSetting = ref(false)
|
export const bannerEnabledSetting = ref(false)
|
||||||
|
|
||||||
|
/** reactive — نمایش UI تهحsاب در حسابداری و ... */
|
||||||
|
export const tahesabEnabledSetting = ref(false)
|
||||||
|
|
||||||
|
let tahesabEnabledFromSettings: boolean | null = null
|
||||||
|
|
||||||
function isSwitchOn(value: string | undefined | null): boolean {
|
function isSwitchOn(value: string | undefined | null): boolean {
|
||||||
const v = (value ?? '').trim().toLowerCase()
|
const v = (value ?? '').trim().toLowerCase()
|
||||||
return v === 'true' || v === '1' || v === 'yes'
|
return v === 'true' || v === '1' || v === 'yes'
|
||||||
@@ -29,6 +34,11 @@ export function setBannerEnabledFromSettings(value: boolean): void {
|
|||||||
bannerEnabledSetting.value = value
|
bannerEnabledSetting.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setTahesabEnabledFromSettings(value: boolean): void {
|
||||||
|
tahesabEnabledFromSettings = value
|
||||||
|
tahesabEnabledSetting.value = value
|
||||||
|
}
|
||||||
|
|
||||||
export function applyBannerEnabledFromRows(rows: Array<{ key?: string; value?: string | null }>) {
|
export function applyBannerEnabledFromRows(rows: Array<{ key?: string; value?: string | null }>) {
|
||||||
const row = rows.find((item) => item.key === 'banner_enabled')
|
const row = rows.find((item) => item.key === 'banner_enabled')
|
||||||
setBannerEnabledFromSettings(row ? isSwitchOn(row.value) : false)
|
setBannerEnabledFromSettings(row ? isSwitchOn(row.value) : false)
|
||||||
@@ -45,7 +55,9 @@ async function bootstrapSettingsFromApi(): Promise<void> {
|
|||||||
const isStoreRow = list.find((item) => item.key === 'is_store')
|
const isStoreRow = list.find((item) => item.key === 'is_store')
|
||||||
const mainWalletRow = list.find((item) => item.key === 'main_wallet_products')
|
const mainWalletRow = list.find((item) => item.key === 'main_wallet_products')
|
||||||
const mainMetalRow = list.find((item) => item.key === 'main_metal')
|
const mainMetalRow = list.find((item) => item.key === 'main_metal')
|
||||||
|
const tahesabRow = list.find((item) => item.key === 'send_to_tahesab')
|
||||||
storeModeFromSettings = isStoreRow ? isSwitchOn(isStoreRow.value) : false
|
storeModeFromSettings = isStoreRow ? isSwitchOn(isStoreRow.value) : false
|
||||||
|
setTahesabEnabledFromSettings(tahesabRow ? isSwitchOn(tahesabRow.value) : false)
|
||||||
applyBannerEnabledFromRows(list)
|
applyBannerEnabledFromRows(list)
|
||||||
setCachedMainMetal(mainMetalRow?.value)
|
setCachedMainMetal(mainMetalRow?.value)
|
||||||
const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
|
const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
|
||||||
@@ -53,6 +65,7 @@ async function bootstrapSettingsFromApi(): Promise<void> {
|
|||||||
} catch {
|
} catch {
|
||||||
storeModeFromSettings = false
|
storeModeFromSettings = false
|
||||||
setBannerEnabledFromSettings(false)
|
setBannerEnabledFromSettings(false)
|
||||||
|
setTahesabEnabledFromSettings(false)
|
||||||
setCachedMainMetal(null)
|
setCachedMainMetal(null)
|
||||||
const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
|
const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
|
||||||
setCachedMainWalletProductIds([])
|
setCachedMainWalletProductIds([])
|
||||||
@@ -77,3 +90,15 @@ export async function initWalletSettingsFromApi(): Promise<void> {
|
|||||||
export function isStoreApp(): boolean {
|
export function isStoreApp(): boolean {
|
||||||
return storeModeFromSettings === true
|
return storeModeFromSettings === true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isTahesabEnabled(): boolean {
|
||||||
|
return tahesabEnabledFromSettings === true
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function initTahesabSettingFromApi(): Promise<boolean> {
|
||||||
|
if (tahesabEnabledFromSettings !== null) return tahesabEnabledFromSettings === true
|
||||||
|
|
||||||
|
await bootstrapSettingsFromApi()
|
||||||
|
|
||||||
|
return tahesabEnabledFromSettings === true
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user